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

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

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

    企业开发基础设施  主目录



目录
相关文章
|
12月前
|
机器学习/深度学习 人工智能 算法
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-15
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-15
317 1
|
机器学习/深度学习 Shell Linux
安装Code-Server 4.0.1 的一些经验
在服务器上面安装自己的Code-Server,实现随时随地在任何终端任何地点,只要客户端的浏览器支持而且有网()就可以获得统一的编程体验
安装Code-Server 4.0.1 的一些经验
|
Web App开发 JavaScript 前端开发
神秘的 shadow-dom 浅析
说到 shadow-dom 可能很多人会很陌生。但是其实我们肯定碰到过,本文主要想简单介绍下 shadow-dom。下面直接进入正文。   shadow-dom 是什么 顾名思义, shadow-dom,直译的话就是 影子dom ?我觉得可以理解为潜藏在黑暗中的 DOM 结构,也就是我们无法直接控制操纵的 DOM 结构。
1281 0
|
6天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
17天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1320 7
|
5天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
296 129
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
4天前
|
监控 JavaScript Java
基于大模型技术的反欺诈知识问答系统
随着互联网与金融科技发展,网络欺诈频发,构建高效反欺诈平台成为迫切需求。本文基于Java、Vue.js、Spring Boot与MySQL技术,设计实现集欺诈识别、宣传教育、用户互动于一体的反欺诈系统,提升公众防范意识,助力企业合规与用户权益保护。
|
16天前
|
机器学习/深度学习 人工智能 前端开发
通义DeepResearch全面开源!同步分享可落地的高阶Agent构建方法论
通义研究团队开源发布通义 DeepResearch —— 首个在性能上可与 OpenAI DeepResearch 相媲美、并在多项权威基准测试中取得领先表现的全开源 Web Agent。
1388 87