企业开发基础设施--类厂服务

简介: 类厂服务的主要功能是简化创建具体工厂任务,使工厂访问代码和工厂创建代码解藕。类厂服务是以抽象工厂模式为基础,并且在其上进行再综合。    在正式进入正题之前,为了方便后面的叙述,先要澄清一些概念,把上下文(Context)搭建起来,然后,我们再在这个上下文中进行讨论。
    类厂服务的主要功能是简化创建具体工厂任务,使工厂访问代码和工厂创建代码解藕。类厂服务是以抽象工厂模式为基础,并且在其上进行再综合。
    在正式进入正题之前,为了方便后面的叙述,先要澄清一些概念,把上下文(Context)搭建起来,然后,我们再在这个上下文中进行讨论。

    首先是两个基本定义:族和系列。(这两个概念是我自创的,不知道常用的术语是什么,知道的朋友请留言告诉我:))
(1)族   -- Category,就是指特定的一类物品。比如服装是一种Category,食物又是一种Category。
        在程序设计和实现中,一个族对应着一个抽象工厂,而我们的当前系统可能会牵涉到多个族。 
 (2)系列 -- Style,指某个族中的某个风格。比如可以把服装的品牌当作Style,一个品牌对应一种Style。

    为了更容易理解,看看IFactory的继承结构就清楚了:
    ///   <summary>
    
///  IFactory 抽象工厂接口的基础接口。所有的抽象工厂接口均从此接口继承。 
    
///   </summary>
     public   interface  IFactory
    {
        
///   <summary>
        
///  族名称 ,在抽象工厂这一层就可以确定CategoryName了
        
///   </summary>         
         string  CategoryName{ get  ;} // 比如是"服装",还是"食物"

        
///   <summary>
        
///  系列名、风格名,需要到具体工厂那一层才确定的了
        
///   </summary>
         string  StyleName{ get  ;}   // 比如耐克、李宁
    }

    
// 抽象工厂IFoodFactory ,族已经确定
     public   interface  IFoodFactory :IFactory
    {
        Apple GetApple() ;
        Rice  GetRice() ;
    }

    
// 具体工厂ChineseFoodFactory ,风格(系列)已经确定
     public   interface  ChineseFoodFactory : IFoodFactory
    {
    }

    
public   interface  JapaneseFoodFactory : IFoodFactory
    {
    }
    


    其次,需要给出当前系统基本假设
(1)不会引入新的族(Category)。因为只要引入新的族,系统肯定需要进行大的修改。因为原系统对新Category一无所知。
(2)系统不会混用同一族中不同的风格。比如不会有一个人上面穿李宁的运动服,下面却穿耐克的鞋子:)

    接下来,我们就能讨论类厂服务了。类场服务的目的主要有两个:
(1)如果系统原先使用Category A族中Style A系列的产品,当系统需要更换到Style B,应该通过修改配置做到(比如把具体工厂A改为具体工厂B),或者仅需要修改相关的几行代码。
(2)隐藏远程工厂与本地工厂的区别。也就是说,系统中不用关心所引用的工厂实例是本地的,还是remoting的。这个也可以通过更改配置来把原来使用本地对象配置为使用远程对象,而我们的系统根本不受影响。

    为了获取具体的工厂实例,需要得到诸如该具体工厂类型名、位置等信息,这些信息通过FactoryInformation来封装。
///   <summary>
    
///  FactoryInformation 通过反射创建对应的工厂时,需要这些相关信息
    
///  (1)当为非远程时,typeName为具体工厂类型名,如果为远程,typeName通常抽象工厂接口类型,如typeof(IFoodFactory)。
    
///  (2)assemblyName参数对现有族中添加一个新系列提供了支持,可以将新系列放在一个独立dll中,然后,修改配置,
    
///     使系统从此使用新系列的对象。
    
///   </summary>
     public   class  FactoryInformation
    {
        
private   string  factoryID ; // 类厂唯一标识
         private   string  typeName  ; // 类厂的类型全名称
         private   string  assemblyPath ; // 类厂所在配件
         private   string  location  ; // http://RemoteServer1/ClassFactory.rem
         private   bool    isInCurrentAssembly  =   true  ; // 是否在当前exe配件中

        
public  FactoryInformation( string  factory_ID , string  type_Name , string  assPath , string  loc , bool  isInCurAssem)
        {
            
this .factoryID              =  factory_ID ;
            
this .typeName              =  type_Name ;
            
this .assemblyPath          =  assPath ;
            
this .location              =  loc ;
            
this .isInCurrentAssembly  =  isInCurAssem ;
        }

        
#region  property       
        
#region  IsRemoting
        
public   bool  IsRemoting   // 是否为远程
        {
            
get
            {
                
if (( this .location  ==   null || ( this .location.Trim()  ==   "" ))
                {
                    
return   false  ;
                }

                
return   true  ;
            }
        }
        
#endregion

        
#region  IsInCurrentAssembly
        
public   bool  IsInCurrentAssembly  // 是否在当前的配件中
        {
            
get
            {
                
return   this .isInCurrentAssembly ;
            }
        }
        
#endregion
        
#endregion
    }
    
    上面的代码省略了一些省略简单属性。其余的已经完全可以通过注释来解释清楚了,需要指出每个工厂都有一个唯一标志factoryID,根据这个标志,我们可以要求类厂服务基础设施来为我们创建指定的工厂对象。
   
     类厂服务是一个静态类,外貌如下:
public   class  ClassFactoryService
    {        
        
public   static   void  Initialize(IFactoryInfoGetter fiGetter) ;    
        
public   static  IFactory GetFactory( string  factoryID) ;        
    }
    其中只有两个静态方法,一个用于初始化,一个用于获取工厂对象。
    初始化需要有个IFactoryInfoGetter的参数,IFactoryInfoGetter用于获取指定工厂的FactoryInformation, 通常将所有的FactoryInformation存放于配置文件中。IFactoryInfoGetter接口定义如下:
public   interface  IFactoryInfoGetter
    {
        FactoryInformation GetFactoryInformation(
string  factoryID) ;    
    }
    ClassFactoryService.Initialize一般在系统启动的时候调用。这样以后就可以正常的使用类厂服务了。下面看看关键的GetFactory方法的实现,看它是如何达到前面提到的类厂服务的两个目的的。
public   static  IFactory GetFactory( string  factoryID) 
        {
            
if (ClassFactoryService.factoryInfoGetter  ==   null )
            {
                
return   null  ;
            }

            FactoryInformation factoryInfo 
=  ClassFactoryService.factoryInfoGetter.GetFactoryInformation(factoryID) ;
            
if (factoryInfo  ==   null )
            {
                
return   null  ;
            }

            Type factoryType 
=   null  ;
            
// 远程
             if (factoryInfo.IsRemoting)
            {            
                factoryType 
=  Type.GetType(factoryInfo.TypeName) ; // 此时factoryType通常为抽象工厂接口类型
                 return  (IFactory)Activator.GetObject(factoryType ,factoryInfo.Location) ;
            }

            
// 本地,在当前配件中
             if (factoryInfo.IsInCurrentAssembly)
            {
                factoryType 
=  Type.GetType(factoryInfo.TypeName) ;
                
return  (IFactory)Activator.GetObject(factoryType , null ) ;
            }

            
// 本地,不在当前配件中,但目标配件已被加载
            factoryType  =  Type.GetType(factoryInfo.TypeName) ;
            
if (factoryType  !=   null )
            {
                
return  (IFactory)Activator.GetObject(factoryType , null ) ;
            }

            
// 本地,不在当前配件中,而且未加载目标配件
            Assembly destAssembly  =  Assembly.LoadFrom(factoryInfo.AssemblyPath) ;
            
if (destAssembly  ==   null )
            {
                
return   null  ;
            }

            factoryType 
=  destAssembly.GetType(factoryInfo.TypeName) ;
            
return  (IFactory)Activator.GetObject(factoryType ,factoryInfo.Location) ;
        }
    
    注释已经很好的说明了发生的一切,其中最主要的就是使用了简单的反射技术和Remoting技术。到这里,我们的任务已经完成了,但是有些注意事项需要提出来:
(1)当在远程服务器上发布工厂类时,客户端可以通过下面三种方式得到其类型信息:
a.  把远程对象的接口程序集部署到客户端,即客户端可以得到其对应的抽象工厂接口信息。
b. 把实际的工厂类部署到客户端。
c. 在客户端部署一组"空类" ,这组类实现了抽象工厂接口,并且从MarshalByRefObject继承。可以通过SoapSuds.exe完成。(推荐)

(2)如果类工厂配置为remoting,那么该类工厂产生的所有物品都必须实现MarshalByRefObject。

    关于类厂服务,我自己已经实现的就这么多,还有很多思路没有实现出来,等那些新想法成型后再拿出来和大家讨论。

    企业开发基础设施  主目录



目录
相关文章
|
2月前
|
运维 持续交付 云计算
云计算中的基础设施自动化:IaC(基础设施即代码)的崛起与实践
云计算中的基础设施自动化:IaC(基础设施即代码)的崛起与实践
54 0
|
5月前
|
监控 安全 数据可视化
SaaS化大型微服务架构智慧工地云平台源码
SaaS化大型微服务架构智慧工地云平台源码
44 0
|
10月前
|
开发框架 负载均衡 小程序
一款针对中小学研发的智慧校园云平台源码 SaaS私有云部署模式
系统后台采用Java开发语言,前端采用VUE开发框架 2、系统采用微服务springcloud架构的作为后台服务器架构 3、系统支持搭建开发具备服务注册发现、客户负载均衡、服务间通信的微服务架构 4、系统支持使用SpringCloud Eurek、SpringCloud Ribbon、restTemplate 等组件进行开发 5、数据库MySQL5.7 6、移动端小程序使用小程序原生语言开发 7、电子班牌固件安卓7.1;使用Java Android原生 8、elmentui ,Quartz,jpa,jwt
一款针对中小学研发的智慧校园云平台源码 SaaS私有云部署模式
|
11月前
|
小程序 安全 Java
智慧校园电子班牌系统全套源码,前后端分离架构,SaaS云平台,私有云部署
智慧校园电子班牌系统全套源码包含:电子班牌管理系统、成绩管理系统、考勤人脸刷卡管理系统、综合素养评价系统、请假管理系统、电子班牌发布系统、校务管理系统、小程序移动端、教师后台管理系统、SaaS运营云平台。 前后端分离架构,SaaS云平台,私有云部署。 1、使用springboot框架Java+vue2 2、数据库MySQL5.7 3、移动端小程序使用小程序原生语言开发 4、电子班牌固件安卓7.1;使用Java Android原生 5、elmentui ,Quartz,jpa,jwt
智慧校园电子班牌系统全套源码,前后端分离架构,SaaS云平台,私有云部署
|
12月前
|
云安全 供应链 监控
《2023云原生实战案例集》——04 互联网——Salesforce 容器化改造,成功落地安全可信软件供应链
《2023云原生实战案例集》——04 互联网——Salesforce 容器化改造,成功落地安全可信软件供应链
|
运维 数据可视化 程序员
低代码软件交付的五大优势
从项目角度出发低代码比传统软件交付有五大优势。具体包括:POC优势、SOW优势、交付模式优势、可复用优势和交付周期优势。
低代码软件交付的五大优势
|
机器学习/深度学习 人工智能 安全
iNeuOS专注自主可控工业互联网平台,为中小企业提供全新解决方案
工业互联网 物联网 Web组态 商业BI 实景视频 人工智能 iNeuOS
iNeuOS专注自主可控工业互联网平台,为中小企业提供全新解决方案
|
数据采集 搜索推荐 数据可视化
使用OA系统构建数据中心的解决方案
OA系统为组织构建一站式、智能化的数据中心,让数据收集、汇总、分析更方便及时,有效助力组织决策…
|
监控 安全 IDE
你的云还是手动挡的吗?云计算和基础设施自动化不可或缺的五大工具
没有一个工具是万能的,但我们依然能找出那些预算内投入产出比最高的优秀产品。
|
存储 虚拟化 监控
带你读《企业私有云建设指南》之二:企业云计算涉及的技术选型和管理
企业私有云建设需求旺盛,在架构设计和技术选型过程中应该结合自己公司的实际情况,因地制宜。本书给了很好的经验分享和思路,虽然是本技术书,但文笔流畅、平实细致,内容上也涉及了私有云建设的很多方面,值得细细阅读和品味!