一.简单工厂模式

末鹿安然 提交于 2019-11-29 14:33:08

🏭 简单工厂模式

​ 引言:设计模式1、2、3篇将会介绍三个工厂模式,分别为简单工厂模式、工厂方法模式和抽象工厂模式,三个工厂模式在实际运用中的频率也很高。

​ 本篇介绍的是三个工厂模式中最基础的简单工厂模式,但是实际运用中也是最常见的,博客构造大体分为四个部分:第一部分是对设计模式的官方解释,先对我们对设计模式有一个较为正统的了解;第二部分是通过生活中的例子解释,官方的概念都是很抽象的,强行记概念对自己帮助不大,通过例子可以让我们对设计模式有一个更深的印象;第三部分是设计模式的抽象编程,是设计模式的骨架,有了前面的例子,理解这一部分并不难;最后一部分是对本篇所讲的设计模式的使用场景和优缺点总结。

1.何为简单工厂模式❓

介绍:

​ 简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

该模式中包含的角色及其职责:🕺

  1. 工厂(Creator)角色
    简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
  2. 抽象产品(Product)角色
    简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  3. 具体产品(Concrete Product)角色
    是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

2.情境再现✨

情景:

说起操作系统,市面上大概可以分为三种:

  1. Windows操作系统
  2. Linux操作系统
  3. Mac OS操作系统,

​ 现在老板有个需求,根据用户使用的操作系统的不同,分别调用不同操作系统的 SayHello()方法,和用户打招呼,需求来了就得办事,接下来秀出代码。

编写代码:

初始代码:
        static void Main(string[] args)         {             Console.WriteLine("请选择你的操作系统:\r\n");             Console.WriteLine("A.Windows操作系统\r\n");             Console.WriteLine("B.Linux操作系统\r\n");             Console.WriteLine("C.Mac OS做系统\r\n");             string systemType = Console.ReadLine();             switch (systemType)             {                 case "A":                     Console.WriteLine("你好,我是Windows操作系统,很高兴为您服务~");                     break;                 case "B":                     Console.WriteLine("你好,我是Linux操作系统,很高兴为您服务~");                     break;                 case "C":                     Console.WriteLine("你好,我是Mac OS,很高兴为您服务~");                     break;                 default:                     Console.WriteLine("系统不支持,不能向您问好!");                     break;             }             Console.ReadKey();

结果:

​ 虽然功能是实现了,但是过程式的思维却使得我们的程序只为满足当前的需求,程序不容易维护不容易扩展,更不容易复用,从而达不到高质量代码的要求,并且业务逻辑和客户端耦合度太高

​ 我们应道抛弃过程式的思维,转变为面向对象的分析设计编程思想, 开始考虑通过封装、继承、多态把程序的耦合度降低用设计模式使得程序更加的灵活,容易修改,并且易于复用。

业务封装后的代码:

操作系统类

    /// <summary>     /// 操作系统类     /// </summary>     public class OS     {         public static string SayHello(string systemType)         {             string result = string.Empty;             switch (systemType)             {                 case "A":                     result = "你好,我是Windows操作系统,很高兴为您服务~";                     break;                 case "B":                     result = "你好,我是Linux操作系统,很高兴为您服务~";                     break;                 case "C":                     result = "你好,我是Mac OS,很高兴为您服务~";                     break;                 default:                     result = "系统不支持,不能向您问好!";                     break;             }             return result;         }     }

客户端代码

        static void Main(string[] args)         {             Console.WriteLine("请选择你的操作系统:\r\n");             Console.WriteLine("A.Windows操作系统\r\n");             Console.WriteLine("B.Linux操作系统\r\n");             Console.WriteLine("C.Mac OS做系统\r\n");             string systemType = Console.ReadLine();             string result = OS.SayHello(systemType);             Console.WriteLine(result);             Console.ReadKey();         }

​ 通过这样的方式,我们将业务和界面完全分离了,如果之后又来了一个新的操作系统,比如鸿蒙🙃,只需要在OS类Switch分支上多增加一个判断就行了。

But...这样却违反了

开放封闭原则

——软件实体应当对扩展开放,对修改关闭,当我们修改了OS类时,也破坏了这个类,如果SayHello方法很复杂,当我们修改的时候难免会出错,之后我们用🏭简单工厂模式代码。
使用简单工厂模式:

OS父类:只包含抽象的逻辑方法

    /// <summary>     /// 操作系统父类     /// </summary>     public class OS     {         public virtual string SayHello()         {             string result = string.Empty;             return result;         }     }

具体的操作系统类

    /// <summary>     /// Windows类     /// </summary>     class WindowsOS : OS     {         public override string SayHello()         {             string result = "你好,我是Windows操作系统,很高兴为您服务~";             return result;         }     }     /// <summary>     /// Linux系统类     /// </summary>     class LinuxOS : OS     {         public override string SayHello()         {             string result = "你好,我是Linux操作系统,很高兴为您服务~";             return result;         }     }     /// <summary>     /// Mac OS系统类     /// </summary>     class MacOS : OS     {          public override string SayHello()         {             string result = "你好,我是Mac OS操作系统,很高兴为您服务~";             return result;         }     }     /// <summary>     /// 其他系统类     /// </summary>     class OtherOS : OS     {          public override string SayHello()         {             string result = "系统不支持,不能向您问好!";             return result;         }     }

OSFactory工厂类

    class OSFactory     {         public static OS CreateOS(string systemType)         {             OS os = null;             switch (systemType)             {                 case "A":                     os = new WindowsOS();                     break;                 case "B":                     os = new LinuxOS();                     break;                 case "C":                     os = new MacOS();                     break;                 default:                     os = new OtherOS();                     break;             }             return os;         }     }

客户端

            //根据字段不同‘生产不同’的OS类             OS result = OSFactory.CreateOS("A");             Console.WriteLine(result.SayHello());             Console.ReadKey();

​ 不管你是Windows操作系统还是Linux操作系统都可以使用这段代码实现功能,当我们要增加一个操作系统,我们只需要添加一个相应的操作系统类,并且需要在工厂类Switch分支上增加一个判断,这样我们就实现了对扩展开放,但还没有对修改关闭,这点在工厂方法模式中得到了一定的克服。

3.简单工厂模式模式“骨架”☃

简单工厂模式UML图:

创建步骤:

  • 创建抽象产品类 & 定义具体产品的公共接口;
  • 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
  • 创建工厂类,通过创建静态方法根据传入不同参数从而创建不同具体产品类的实例;
  • 外界通过调用工厂类的静态方法,传入不同参数从而创建不同具体产品类的实例

4.优缺点及使用场景📊

优点

​ 工厂类是整个模式的关键。包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的。明确了各自的职责和权利,有利于整个软件体系结构的优化。

缺点

​ 由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
​ 当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求。这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
这些缺点在工厂方法模式中得到了一定的克服。

使用场景

  1. 工厂类负责创建的对象比较
  2. 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
  3. 由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。

————————————————————————————————————————————

版权声明:本文为吴恺的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
为获得更好的阅读体验,推荐至我的个人博客阅读:https://www.wukailiving.cn/yi-jian-dan-gong-han-mo-shi.html
原文地址:https://www.cnblogs.com/zaijianba/p/11519653.html
如有不足之处,欢迎指正!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!