zoukankan      html  css  js  c++  java
  • 设计模式之抽象工厂(AbstractFactory)

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

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

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

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

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

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

    代码:
     

    客户程序依赖的抽象部分
    #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

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

    客户程序
     //客户程序
        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();
            }
        }

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

    具体类和工厂的实现
      #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

    正式调用: 

    代码
        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添加到程序目录下,然后修改配置文件即可,也不需要修改原来已经稳定运行的程序。

  • 相关阅读:
    python抓取网页图片
    Socket通信之Java学习(一)
    python打包成window可执行程序
    linux下安装java
    SpringBoot系列:五、SpringBoot使用Actuator
    SpringBoot系列:四、SpringBoot集成JPA
    SpringBoot系列:三、SpringBoot中使用Filter
    SpringBoot系列:二、SpringBoot的配置文件
    SpringBoot系列:一、SpringBoot搭建
    .Net Core使用IConfiguration来处理Json文件
  • 原文地址:https://www.cnblogs.com/stulife/p/2265251.html
Copyright © 2011-2022 走看看