企业开发基础设施--类厂服务-阿里云开发者社区

开发者社区> zhuweisky> 正文

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

简介: 类厂服务的主要功能是简化创建具体工厂任务,使工厂访问代码和工厂创建代码解藕。类厂服务是以抽象工厂模式为基础,并且在其上进行再综合。    在正式进入正题之前,为了方便后面的叙述,先要澄清一些概念,把上下文(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。

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

    企业开发基础设施  主目录



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
我为什么要写:新书《离线和实时大数据开发实战》
新书《离线和实时大数据开发实战》 购买链接(机械工业出版社官方淘宝店铺) 感谢@薛奎 和@空无 大大写推荐书评。 空无和薛奎的书评 大数据技术一直是个领先互联网公司的必备核心技术,阿里巴巴最近10年一直在持续加大投入,并将大数据处理技术用于大量的大规模业务场景。每年双十一对实时、离线技术也都是极限的考验,而作者就是在这样的环境下成长起来,基于真实业务场景钻研相关的技术,既有实战也有
3101 0
开放下载!《无需从0开发 平头哥教你1天上手蓝牙Mesh应用解决方案》
弄潮新基建,玩转智能生活!《无需从0开发 平头哥教你1天上手蓝牙Mesh应用解决方案》电子书现已开放下载,立即加入书单吧!
14427 0
微信小程序开发(6) SSL证书及HTTPS服务器
1. 域名 在万网购买,略   2. 云服务器 阿里云购买,略   3. 安装lnmp 使用lnmp.org程序,略   4. 申请证书 阿里云-管理控制台-安全(云盾)-证书服务-购买证书证书类型: 免费型DV SSL选择品牌: Symantec 购买成功后,绑定域名,配置DNS解析记录生效   5.
2579 0
国家质量基础设施系统开发,NQI一站式综合服务平台建设
质量基础设施是有机融合计量、标准、认证认可、检验检测、质量管理等要素形成的体系,是推动高质量发展的技术支撑,是构建现代化经济体系的重要条件。质量基础设施与广大人民群众的获得感、幸福感、安全感息息相关。
53 0
NDK OpenGL ES 3.0 开发(十三):实例化(Instancing)
OpenGL ES 实例化(Instancing)是一种只调用一次渲染函数就能绘制出很多物体的技术,可以实现将数据一次性发送给 GPU ,告诉 OpenGL ES 使用一个绘制函数,将这些数据绘制成多个物体。
75 0
Asp.net MVC 3 开发企业网站系统仿照博客园部分功能--总体设计
在使用Asp.net MVC3 开发企业网站系统的提议得到了广大园友的热情鼓励,也使我更加有信心和决心把这个简单的系统完成的希望。 前两篇索引:Asp.net MVC 3 开发一个简单的企业网站系统      Asp.net MVC 3 开发简单的企业系统开篇--数据库 麻雀虽小,五脏俱全。
1021 0
+关注
zhuweisky
从事软件开发行业十多年,专注于网络通信技术和网络语音视频技术,擅长系统架构设计、系统性能优化等。zhuweisky.cnblogs.com
300
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《Nacos架构&原理》
立即下载
《看见新力量:二》电子书
立即下载
云上自动化运维(CloudOps)白皮书
立即下载