温故而知新:设计模式之抽象工厂(AbstractFactory)

简介: 抽象工厂主要用来解决多个系列的对象实例问题。 问题的应用场景(来源于李建忠老师的webcast讲座): 如果有一款游戏,里面有"道路,房屋,隧道,丛林"这四类基本设施,而且不同的地图(比如中国区,印度区,欧美区)这些设施的风格各有特色,比如中国区应该是中国风格,印度区可能是古典风格,欧美区可能是现代风格.

抽象工厂主要用来解决多个系列的对象实例问题。

问题的应用场景(来源于李建忠老师的webcast讲座):

如果有一款游戏,里面有"道路,房屋,隧道,丛林"这四类基本设施,而且不同的地图(比如中国区,印度区,欧美区)这些设施的风格各有特色,比如中国区应该是中国风格,印度区可能是古典风格,欧美区可能是现代风格...

并且这些基本设施的风格还有可能会一直不断增加,作为程序员/架构师,您想如何让以后的维护/升级变得更轻松,比如新增加一种风格时,最好只要改改配置,顺便发个新的dll复制到安装目录就完事,而不是把原来的类似

xxx = new ChineseStyleRoad(),全部改成xxx = new NewStyleRoad()...

分析:OO思想中有一个重要原则,即开放封闭原则,展开来讲就是 对修改(也称变化)封闭(也称封装),而对扩展(比如在原来框架上的功能增加)开放。本例场景中的变化点,就于在基础设施风格的变化。

代码:

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 客户程序依赖的抽象部分
#region  client程序依赖的抽象类(这些类之间彼此可能有交互)和抽象工厂,所有系列对象创建过程中的变化封装于此
    
// 道路
     public   abstract   class  Road {
        
public   abstract   void  Show();
    }

    
// 房屋
     public   abstract   class  Building {
        
public   abstract   void  Show();
    }

    
// 地道
     public   abstract   class  Tunnel {
        
public   abstract   void  Show();
    }

    
// 从林
     public   abstract   class  Jungle {
        
public   abstract   void  Show();
    }

    
// 客户依赖的抽象工厂
     public   abstract   class  FacilitiesFactory 
    {
        
public   abstract  Road CreateRoad();

        
public   abstract  Building CreateBuilding();

        
public   abstract  Tunnel CreateTunnel();

        
public   abstract  Jungle CreateJungle();

    }
    
#endregion

封装好变化点后,客户端程序就可以这样调用了:

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 客户程序
  // 客户程序
     public   class  GameManager 
    {
        FacilitiesFactory _facilitiesFactory;
        Road _road;
        Building _building;
        Tunnel _tunnel;
        Jungle _jungle;

        
public  GameManager(FacilitiesFactory f) 
        {
            
this ._facilitiesFactory  =  f;
        }

        
public   void  BuildGameFacilities() 
        {
            _road 
=  _facilitiesFactory.CreateRoad();
            _building 
=  _facilitiesFactory.CreateBuilding();
            _jungle 
=  _facilitiesFactory.CreateJungle();
            _tunnel 
=  _facilitiesFactory.CreateTunnel();
        }

        
public   void  Run() 
        {
            _road.Show();
            _building.Show();
            _jungle.Show();
            _tunnel.Show();
        }
    }

可以看到,这里并没有任何具体类的依赖,也就是说基本解除了依赖,但不管如何抽象最终还是要得到具体类的实例,下面是具体类和工厂的实现: 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 具体类和工厂的实现
   #region  具体类/工厂的实现(实际开发中,具体的某一系列对象可单独用独立项目发布成独立的程序集,以应对变化,比如增加一个新系统时,仅需要修改配置,再加一个dll就可实现批量替换所有子对象)
    
#region // 现代风格的road,building,tunnel,jungle及对应的工厂
    
public   class  ModernRoad : Road 
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 现代风格的道路已经建成! " );
        }
    }

    
public   class  ModernBuilding : Building 
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 现代风格的房屋已经建成! " );
        }
    }

    
public   class  ModernTunnel : Tunnel
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 现代风格的隧道已经建成! " );
        }
    }

    
public   class  ModernJungle : Jungle
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 现代风格的丛林已经建成! " );
        }
    }

    
public   class  ModernFacilityisFactory : FacilitiesFactory 
    {
        
public   override  Road CreateRoad() 
        {
            
return   new  ModernRoad();
        }

        
public   override  Building CreateBuilding()         
        {
            
return   new  ModernBuilding();
        }

        
public   override  Tunnel CreateTunnel() 
        {
            
return   new  ModernTunnel();
        }

        
public   override  Jungle CreateJungle() 
        {
            
return   new  ModernJungle();
        }
    }
    
#endregion

    
#region // 古典风格的road,building,tunnel,jungle及对应的工厂
    
public   class  ClassicRoad : Road
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 古典风格的道路已经建成! " );
        }
    }

    
public   class  ClassicBuilding : Building
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 古典风格的房屋已经建成! " );
        }
    }

    
public   class  ClassicTunnel : Tunnel
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 古典风格的隧道已经建成! " );
        }
    }

    
public   class  ClassicJungle : Jungle
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 古典风格的丛林已经建成! " );
        }
    }

    
public   class  ClassicFacilityisFactory : FacilitiesFactory
    {
        
public   override  Road CreateRoad()
        {
            
return   new  ClassicRoad();
        }

        
public   override  Building CreateBuilding()
        {
            
return   new  ClassicBuilding();
        }

        
public   override  Tunnel CreateTunnel()
        {
            
return   new  ClassicTunnel();
        }

        
public   override  Jungle CreateJungle()
        {
            
return   new  ClassicJungle();
        }
    }
    
#endregion

    
#region // 中国风格的road,building,tunnel,jungle及对应的工厂
    
public   class  ChineseRoad : Road
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 中国风格的道路已经建成! " );
        }
    }

    
public   class  ChineseBuilding : Building
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 中国风格的房屋已经建成! " );
        }
    }

    
public   class  ChineseTunnel : Tunnel
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 中国风格的隧道已经建成! " );
        }
    }

    
public   class  ChineseJungle : Jungle
    {
        
public   override   void  Show()
        {
            Console.WriteLine(
" 中国风格的丛林已经建成! " );
        }
    }

    
public   class  ChineseFacilityisFactory : FacilitiesFactory
    {
        
public   override  Road CreateRoad()
        {
            
return   new  ChineseRoad();
        }

        
public   override  Building CreateBuilding()
        {
            
return   new  ChineseBuilding();
        }

        
public   override  Tunnel CreateTunnel()
        {
            
return   new  ChineseTunnel();
        }

        
public   override  Jungle CreateJungle()
        {
            
return   new  ChineseJungle();
        }
    }
    
#endregion
    
#endregion

正式调用: 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
     class  Program
    {
        
static   void  Main( string [] args)
        {
            
// 注意下面的写法:
            
// Assembly.Load("这是里程序集的名称")
            
// CreateInstance("这是具体类的完整表示法,即:命令空间.类名")
            FacilitiesFactory _factory  =  (FacilitiesFactory)Assembly.Load( " AbstractFactory " ).CreateInstance(ConfigurationManager.AppSettings[ " FactoryType " ].ToString());

            GameManager gm 
=   new  GameManager(_factory);
            gm.BuildGameFacilities();
            gm.Run();
            Console.Read();
            
        }
    }

当然这里还有一个配置文件:

<? xml version="1.0" encoding="utf-8"  ?>
< configuration >
  
< appSettings >
    
< add  key ="FactoryType"  value ="AbstractFactory.ClassicFacilityisFactory" />
  
</ appSettings >
</ configuration >

可以看到,利用抽象工厂再配合反射,如果想把所有"中国风格"的设施换成"古典风格"的设施,只需要把配置文件中的<add key="FactoryType" value="AbstractFactory.ChineseFacilityisFactory"/>换成   <add key="FactoryType" value="AbstractFactory.ClassicFacilityisFactory"/>,原代码一行都不用改,是不是很轻松! 如果新增了一种风格,也只要把新增加的"具体类和工厂"所对应的程序集dll添加到程序目录下,然后修改配置文件即可,也不需要修改原来已经稳定运行的程序。

img_891411fef3bcd5b3a0cf7d749aa50e13.png

目录
相关文章
|
1月前
|
设计模式
设计模式之抽象工厂
设计模式之抽象工厂
|
3月前
|
设计模式 Java
常用设计模式(工厂方法,抽象工厂,责任链,装饰器模式)
有关设计模式的其他常用模式请参考 单例模式的实现 常见的设计模式(模板与方法,观察者模式,策略模式)
39 2
|
6月前
|
设计模式 Java 关系型数据库
解锁设计模式的神秘面纱:编写无懈可击的代码之抽象工厂设计模式
解锁设计模式的神秘面纱:编写无懈可击的代码之抽象工厂设计模式
23 0
|
3月前
|
设计模式
设计模式-抽象工厂
设计模式-抽象工厂
|
6月前
|
设计模式 架构师
设计模式之抽象工厂
设计模式之抽象工厂
|
1月前
|
设计模式 关系型数据库 数据库
【C++ 设计模式 工厂模式对比】深入探索设计模式:工厂方法与抽象工厂的比较与对照
【C++ 设计模式 工厂模式对比】深入探索设计模式:工厂方法与抽象工厂的比较与对照
21 1
|
3月前
|
设计模式 Java 数据库连接
Java设计模式--简单工厂、工厂方法和抽象工厂之间的区别
设计模式中的工厂模式(Factory Design pattern)是一个比较常用的创建型设计模式,其中可以细分为三种:简单工厂(Simple Factory)、工厂方法(Factory Method)和抽象工厂(Abstract Factory)。那么三者有什么区别呢?
99 1
Java设计模式--简单工厂、工厂方法和抽象工厂之间的区别
|
3月前
|
设计模式 安全 数据库
创建型设计模式-单例模式/工厂模式/抽象工厂
创建型设计模式-单例模式/工厂模式/抽象工厂
37 0
|
9月前
|
设计模式 前端开发 JavaScript
前端实现设计模式之抽象工厂
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体的类。抽象工厂模式可以帮助我们实现对象的创建与使用的解耦,同时提供了一种灵活的方式来创建不同产品族的对象。本文将介绍如何在前端中实现抽象工厂模式,并提供具体的代码示例和解读。
|
4月前
|
设计模式 SQL 数据库连接
设计模式之抽象工厂模式--创建一系列相关对象的艺术(简单工厂、工厂方法、到抽象工厂的进化过程,类图NS图)
设计模式之抽象工厂模式--创建一系列相关对象的艺术(简单工厂、工厂方法、到抽象工厂的进化过程,类图NS图)