专栏首页GreenLeavesFactoryMethod工厂方法模式(创建型模式)

FactoryMethod工厂方法模式(创建型模式)

1、工厂方法模式解决的问题

现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路.

前提:抽象变化较慢,实现变化较快(不稳定)

整个抽象的游戏设施建造系统相对变化较慢,本例中只有一个Build的创建方法,而Build内部的方法实现,该实现依赖与各种具体的实现,而这些实现变化的非常频繁,现在虽然只有现代风格和古典风格的房屋和道路的构建,而将来可能会卡通风格、另类风格等各种各样的对象加入到Build方法中来渲染游戏的背景.

在不考虑第三方容器组件(如Unity)和设计模式的情况下,为了快速完成这个任务,我们通常会用以下这种方式编码,代码如下:

    #region 抽象A
    /// <summary>
    /// 抽象的游戏设施建造系统
    /// </summary>
    public class BuildSystem
    {
        /// <summary>
        /// Build方法的逻辑变化较慢(只需要创建2种风格的房屋和道路,总共8个对象),但是风格变化较快,由于需求变化,可能需要创建诸如卡通风格、另类风格等的房屋和道路
        /// </summary>
        public void Builld()
        {
            ModernHouse modernHouseA = new ModernHouse();
            ModernHouse modernHouseB = new ModernHouse();
            ModernRoad modernRoadA = new ModernRoad();
            ModernRoad modernRoadB = new ModernRoad();
            ClassicalHouse classicalBuildA = new ClassicalHouse();
            ClassicalHouse classicalBuildB = new ClassicalHouse();
            ClassicalRoad classicalRoadA = new ClassicalRoad();
            ClassicalRoad classicalRoadB = new ClassicalRoad();
            //下面是具体的对象实例操作,如现代化房屋虽然有两个实例,但是可能两个可能高矮、外形不同等
        }
    } 
    #endregion

    #region 实现细节b
    /// <summary>
    /// 现代风格的房屋
    /// </summary>
    public class ModernHouse { }

    /// <summary>
    /// 现代风格的道路
    /// </summary>
    public class ModernRoad { }

    /// <summary>
    /// 古典风格的房屋
    /// </summary>
    public class ClassicalHouse { }

    /// <summary>
    /// 古典风格的道路
    /// </summary>
    public class ClassicalRoad { } 
    #endregion

客户端调用代码如下:

    class Program
    {
        static void Main(string[] args)
        {
            BuildSystem buildSystem = new BuildSystem();
            buildSystem.Builld();
        }
    }

从oop的角度分析上面的代码:

1、Build方法的主逻辑稳定(变化较慢),构建两种风格的房屋和道路,目前只需要构建8个对象,后续可扩展.

2、虽然上面的代码完成1中的要求,但是无法应对后续的扩展,假设新增加了一个需求,Build方法需要能切换风格,完成卡通和另类风格的房屋和道路的构建,显然上面的代码无法完成这个需求.(当然你可以在BuildSystem中新添一种新的Build方法来满足需求,但是这种方式的代码的重用性差)

3、代码的大致结构如下图:

代码虽然拥有大致的主逻辑,但是和各个子模块糅合在一起,代码复用性差,Build方法(抽象)依赖于其下面的具体实现,如下图:

所以我们需要对代码进行重构.

    /// <summary>
    /// 抽象的游戏建造系统
    /// </summary>
    public class BuildSystem
    {
        /// <summary>
        /// 具体的构建方法,Build方法的逻辑变化较慢(只需要创建2种风格的房屋和道路,总共8个对象),但是风格变化较快,由于需求变化,可能需要创建诸如卡通风格、另类风格等的房屋和道路
        /// </summary>
        public void Build(HouseFactory houseFactoryOne, HouseFactory houseFactoryTwo,RoadFactory roadFactoryOne, RoadFactory roadFactoryTwo)
        {
            House HFirstStyleOne = houseFactoryOne.CreateHouse();
            Console.WriteLine(HFirstStyleOne.ShowHouseStyle());
            House HFirstStyleTwo = houseFactoryOne.CreateHouse();
            Console.WriteLine(HFirstStyleTwo.ShowHouseStyle());
            Road RFirstStyleOne = roadFactoryOne.CreateRoad();
            Console.WriteLine(RFirstStyleOne.ShowRoadStyle());
            Road RFirstStyleTwo = roadFactoryOne.CreateRoad();
            Console.WriteLine(RFirstStyleTwo.ShowRoadStyle());
            House HSecondStyleOne = houseFactoryTwo.CreateHouse();
            Console.WriteLine(HSecondStyleOne.ShowHouseStyle());
            House HSecondStyleTwo = houseFactoryTwo.CreateHouse();
            Console.WriteLine(HSecondStyleTwo.ShowHouseStyle());
            Road RSecondStyleOne = roadFactoryTwo.CreateRoad();
            Console.WriteLine(RSecondStyleOne.ShowRoadStyle());
            Road RSecondTwo= roadFactoryTwo.CreateRoad();
            Console.WriteLine(RSecondTwo.ShowRoadStyle());
        }
    }

    #region 抽象工厂方法
    /// <summary>
    /// 抽象的House工厂方法
    /// </summary>
    public abstract class HouseFactory
    {
        public abstract House CreateHouse();
    }

    /// <summary>
    /// 抽象的Road工厂方法
    /// </summary>
    public abstract class RoadFactory
    {
        public abstract Road CreateRoad();
    }

    #endregion

    #region 工厂方法
    public class ModernHouseFactory : HouseFactory
    {
        public override House CreateHouse()
        {
            return new ModernHouse();
        }
    }

    public class ModerRoadFactory : RoadFactory
    {
        public override Road CreateRoad()
        {
            return new ModernRoad();
        }
    }

    public class ClassicalHouseFactory : HouseFactory
    {
        public override House CreateHouse()
        {
            return new ClassicalHouse();
        }
    }

    public class ClassicalRoadFactory : RoadFactory
    {
        public override Road CreateRoad()
        {
            return new ClassicalRoad();
        }
    }

    public class CartoonHouseFactory : HouseFactory
    {
        public override House CreateHouse()
        {
            return new CartoonHouse();
        }
    }

    public class CartoonRoadFactory : RoadFactory
    {
        public override Road CreateRoad()
        {
            return new CartoonRoad();
        }
    }

    public class AlternativeHouseFactory : HouseFactory
    {
        public override House CreateHouse()
        {
            return new AlternativeHouse();
        }
    }

    public class AlternativeRoadFactory : RoadFactory
    {
        public override Road CreateRoad()
        {
            return new AlternativeRoad();
        }
    }
    #endregion

    #region 抽象
    public abstract class House
    {
        public abstract string ShowHouseStyle();
    }

    public abstract class Road
    {
        public abstract string ShowRoadStyle();
    }
    #endregion

    #region 具体的实现
    public class ModernHouse : House
    {
        public override string ShowHouseStyle()
        {
            return "Modern现代化风格房屋";
        }
    }

    public class ModernRoad : Road
    {
        public override string ShowRoadStyle()
        {
            return "Modern现代化风格道路";
        }
    }

    public class ClassicalHouse : House
    {
        public override string ShowHouseStyle()
        {
            return "Classical古典化风格房屋";
        }
    }

    public class ClassicalRoad : Road
    {
        public override string ShowRoadStyle()
        {
            return "Classical古典化风格道路";
        }
    }

    public class CartoonHouse : House
    {
        public override string ShowHouseStyle()
        {
            return "Cartoon卡通化风格房屋";
        }
    }

    public class CartoonRoad : Road
    {
        public override string ShowRoadStyle()
        {
            return "Cartoon卡通化风格道路";
        }
    }

    public class AlternativeHouse : House
    {
        public override string ShowHouseStyle()
        {
            return "Alternative另类化风格房屋";
        }
    }

    public class AlternativeRoad : Road
    {
        public override string ShowRoadStyle()
        {
            return "Alternative另类化风格道路";
        }
    }
    #endregion

客户端调用代码如下:

    /// <summary>
    /// FactoryMethod工厂方法-创建型模式
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            BuildSystem buildSystem = new BuildSystem();
            buildSystem.Build(new CartoonHouseFactory(), new AlternativeHouseFactory(), new CartoonRoadFactory(),new AlternativeRoadFactory());
            Console.ReadKey();
        }
    }

ok,重构后的代码很好的完成的了需求,而且扩展性更高,这就是FactoryMethod工厂模式,通过工厂模式,完成对主逻辑的整理,让主逻辑不在依赖具体的实现细节,而是依赖于抽象工厂.,通过传入的具体类型的工厂类来完成具体类型的创建,如果后续需要增加具体类型实例的实例,则只需要调用Create方法即可,完成依赖倒置.

重构后的代码如下图:

中间的实折现代表Build方法,主逻辑稳定,圈圈代表抽象工厂类,通过抽象工厂类完成主逻辑和实现的解耦.

虽然工厂模式能很好的解决这一类问题,但是如果具体的实现细节过多,比如在增加N种风格的房屋和道路,这个时候就会存在工厂泛滥的问题?

解决方案如下:

1、使用第三方依赖注入工具,如Unity等  参考控制反转和依赖注入模式

2、使用原型模式,原型模式能很好的解决工厂泛滥的问题.关于原型模式,请参考原型模式(创建型模式)

关于抽象工厂模式和工厂模式的区别:

工厂模式只能解决单个对象的需求变化,实际上面的代码还能进一步进行抽象,对工厂类进行抽象,将现代化的道路和房屋抽象到一起,构成一个现代化风格系列对象创建工厂,这个时候就是工厂模式的升级版-抽象工厂,抽象工厂模式解决系列对象的对象变化.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • FactoryMethod工厂方法模式升级成AbstractFactory抽象工厂模式

    具体参考抽象工厂(AbstractFactory)模式-创建型模式,本文在FactoryMethod工厂方法模式(创建型模式)的基础上进行业务进一步抽象,不做详...

    郑小超.
  • .Net 从零开始构建一个框架之基本实体结构与基本仓储构建

    本系列文章将介绍如何在.Net框架下,从零开始搭建一个完成CRUD的Framework,该Framework将具备以下功能,基本实体结构(基于DDD)、基本仓储...

    郑小超.
  • 原型模式(创建型模式)

    整个抽象的游戏设施建造系统相对变化较慢,本例中只有一个Build的创建方法,而Build内部的方法实现,该实现依赖与各种具体的实现,而这些实现变化的非常频繁,现...

    郑小超.
  • .NET基础拾遗(2)面向对象的实现和异常的处理基础

      在C#中申明一个类型时,只支持单继承(即继承一个父类),但支持实现多个接口(Java也是如此)。像C++可能会支持同时继承自多个父类,但.NET的设计小组认...

    Edison Zhou
  • 在C#中使用依赖注入-工厂模式和工厂方法模式

    工厂模式和工厂方法模式是设计模式中较为常见的两种模式,借助于依赖注入可以更好的发挥模式的特性。本文将通过一个业务需求的变化过程来阐述如何更好的使用设计模式与依赖...

    newbe36524
  • 23种设计模式详解(二)

    是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

    南风
  • 初探Java设计模式4:一文带你掌握JDK中的设计模式

    转自https://javadoop.com/post/design-pattern

    Java技术江湖
  • 初探Java设计模式3:行为型模式(策略,观察者等)

    转自https://javadoop.com/post/design-pattern

    Java技术江湖
  • IOC编程

    2. 开放/封闭原则: 添加任何新行为,应该是扩展到新类中,而不应该直接修改原来运行良好的代码。

    小蜜蜂
  • Java内功心法,行为型设计模式

    使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。

    李红

扫码关注云+社区

领取腾讯云代金券