• 设计模式-创建型-工厂模式


    工厂设计模式:

      顾名思义,该模式是用来生产对象的。在面向对象的设计模式中,万物皆对象,若使用new来创建对象,就会对该对象产生强耦合,假如我们需要更换该对象,那么使用该对象的对象都需要进行修改,这显然违背了开闭原则(OCP)。如果我们使用工厂来产生对象,我们只需要与这个工厂打交道就可以了,无需关心具体的对象,达到解耦的目的。

      接下来我们从实际的案例出发,从无工厂到有工厂的区别。

      去披萨店订购披萨,首先披萨的种类很多(CheesePizza、GreekPizza、DurianPizza等),披萨的制作流程有prepare、bake、cut、box。

    传统模式:

       

     1 internal class Program
     2 {
     3     private static void Main(string[] args)
     4     {
     5         new OrderPizza();
     6     }
     7 }
     8 
     9 internal class OrderPizza
    10 {
    11     public OrderPizza()
    12     {
    13         Pizza pizza = null;
    14         string orderType = "";
    15         do
    16         {
    17             orderType = Console.ReadLine();
    18             if (orderType == "cheese")
    19             {
    20                 pizza = new CheesePizza();
    21                 pizza.setName("芝士披萨");
    22             }
    23             else if (orderType == "greek")
    24             {
    25                 pizza = new GreekPizza();
    26                 pizza.setName("希腊披萨");
    27             }
    28             else
    29             {
    30                 Console.WriteLine("订购失败");
    31                 break;
    32             }
    33             //开始制作
    34             pizza.prepare();
    35             pizza.bake();
    36             pizza.cut();
    37             pizza.box();
    38         } while (true);
    39     }
    40 }
    41 
    42 internal abstract class Pizza
    43 {
    44     private string name;
    45 
    46     public abstract void prepare();
    47 
    48     public void bake()
    49     {
    50         Console.WriteLine($"{this.name} 烘培");
    51     }
    52 
    53     public void cut()
    54     {
    55         Console.WriteLine($"{this.name} 修剪");
    56     }
    57 
    58     public void box()
    59     {
    60         Console.WriteLine($"{this.name} 打包");
    61     }
    62 
    63     public void setName(string name)
    64     {
    65         this.name = name;
    66     }
    67 }
    68 
    69 internal class CheesePizza : Pizza
    70 {
    71     public override void prepare()
    72     {
    73         Console.WriteLine("芝士披萨准备中");
    74     }
    75 }
    76 
    77 internal class GreekPizza : Pizza
    78 {
    79     public override void prepare()
    80     {
    81         Console.WriteLine("希腊披萨准备中");
    82     }
    83 }
    view code

      传统模式的优缺点:

        1、比较好理解,易于操作

        2、违反OCP原则,即对扩展开放,对修改关闭。

        3、这里只订购了两种pizza,若现在又新增了品种DurianPizza,这个时候就需要添加该类以及修改OrderPizza中的代码。从上图中可以看出,OrderPizza依赖抽象类及具体实现类的,那怎样才能切断OrderPizza与类之间的依赖关系呢。于是我们想到,可以定义一个工厂,订购者不需要知道具体pizza的制作流程,只要直到我需要订购什么类型的pizza就行了。

    简单工厂模式:

       

      1 internal class Program
      2 {
      3     private static void Main(string[] args)
      4     {
      5         new OrderPizza();
      6     }
      7 }
      8 
      9 internal class OrderPizza
     10 {
     11     public OrderPizza()
     12     {
     13         Pizza pizza = null;
     14         string orderType = "";
     15         do
     16         {
     17             Console.Write("请输入订购类型:");
     18             orderType = Console.ReadLine();
     19             pizza = SimpleFactory.createPizza(orderType);
     20             if (pizza == null)
     21             {
     22                 Console.WriteLine("订购失败");
     23                 break;
     24             }
     25             //开始制作
     26             pizza.prepare();
     27             pizza.bake();
     28             pizza.cut();
     29             pizza.box();
     30         } while (true);
     31     }
     32 }
     33 
     34 internal static class SimpleFactory
     35 {
     36     public static Pizza createPizza(string orderType)
     37     {
     38         Pizza pizza = null;
     39         do
     40         {
     41             if (orderType == "cheese")
     42             {
     43                 pizza = new CheesePizza();
     44                 pizza.setName("芝士披萨");
     45             }
     46             else if (orderType == "greek")
     47             {
     48                 pizza = new GreekPizza();
     49                 pizza.setName("希腊披萨");
     50             }
     51             else if (orderType == "durian")
     52             {
     53                 pizza = new DurianPizza();
     54                 pizza.setName("榴莲披萨");
     55             }
     56             return pizza;
     57         } while (true);
     58     }
     59 }
     60 
     61 internal abstract class Pizza
     62 {
     63     private string name;
     64 
     65     public abstract void prepare();
     66 
     67     public void bake()
     68     {
     69         Console.WriteLine($"{this.name} 烘培");
     70     }
     71 
     72     public void cut()
     73     {
     74         Console.WriteLine($"{this.name} 修剪");
     75     }
     76 
     77     public void box()
     78     {
     79         Console.WriteLine($"{this.name} 打包");
     80     }
     81 
     82     public void setName(string name)
     83     {
     84         this.name = name;
     85     }
     86 }
     87 
     88 internal class CheesePizza : Pizza
     89 {
     90     public override void prepare()
     91     {
     92         Console.WriteLine("芝士披萨准备中");
     93     }
     94 }
     95 
     96 internal class GreekPizza : Pizza
     97 {
     98     public override void prepare()
     99     {
    100         Console.WriteLine("希腊披萨准备中");
    101     }
    102 }
    103 
    104 internal class DurianPizza : Pizza
    105 {
    106     public override void prepare()
    107     {
    108         Console.WriteLine("榴莲披萨准备中");
    109     }
    110 }
    view code

      简单工厂模式优缺点:

        1、由代码可以看出,虽然简单工厂模式一定程度上减少了因需求变更而导致的代码更改,但是实际仍违背了OCP原则。

        2、所以简单工厂模式只适合产品对象相对较少,且产品固定的需求,对产品变化无常的需求来说显然不适合。

     

    工厂方法设计模式:

      披萨项目需求变更,客户点披萨时可以点不同口味的披萨。 

       

      1 internal class Program
      2 {
      3     private static void Main(string[] args)
      4     {
      5         new BJOrderPizza();
      6     }
      7 }
      8 
      9 internal abstract class OrderPizza
     10 {
     11     public OrderPizza()
     12     {
     13         Pizza pizza = null;
     14         string orderType = "";
     15         do
     16         {
     17             Console.Write("请输入订购类型:");
     18             orderType = Console.ReadLine();
     19             pizza = createPizza(orderType);
     20             if (pizza == null)
     21             {
     22                 Console.WriteLine("订购失败");
     23                 break;
     24             }
     25             //开始制作
     26             pizza.prepare();
     27             pizza.bake();
     28             pizza.cut();
     29             pizza.box();
     30         } while (true);
     31     }
     32 
     33     public abstract Pizza createPizza(string orderType);
     34 }
     35 
     36 internal class BJOrderPizza : OrderPizza
     37 {
     38     public override Pizza createPizza(string orderType)
     39     {
     40         Pizza pizza = null;
     41         if (orderType == "cheese")
     42         {
     43             pizza = new BJCheesePizza();
     44         }
     45         else if (orderType == "greek")
     46         {
     47             pizza = new BJGreekPizza();
     48         }
     49         return pizza;
     50     }
     51 }
     52 
     53 internal class LDOrderPizza : OrderPizza
     54 {
     55     public override Pizza createPizza(string orderType)
     56     {
     57         Pizza pizza = null;
     58         if (orderType == "cheese")
     59         {
     60             pizza = new LDCheesePizza();
     61         }
     62         else if (orderType == "greek")
     63         {
     64             pizza = new LDGreekPizza();
     65         }
     66         return pizza;
     67     }
     68 }
     69 
     70 internal abstract class Pizza
     71 {
     72     private string name;
     73 
     74     public abstract void prepare();
     75 
     76     public void bake()
     77     {
     78         Console.WriteLine($"{this.name} 烘培");
     79     }
     80 
     81     public void cut()
     82     {
     83         Console.WriteLine($"{this.name} 修剪");
     84     }
     85 
     86     public void box()
     87     {
     88         Console.WriteLine($"{this.name} 打包");
     89     }
     90 
     91     public void setName(string name)
     92     {
     93         this.name = name;
     94     }
     95 }
     96 
     97 internal class BJCheesePizza : Pizza
     98 {
     99     public override void prepare()
    100     {
    101         Console.WriteLine("北京的芝士披萨准备中");
    102     }
    103 }
    104 
    105 internal class BJGreekPizza : Pizza
    106 {
    107     public override void prepare()
    108     {
    109         Console.WriteLine("北京的希腊披萨准备中");
    110     }
    111 }
    112 
    113 internal class LDCheesePizza : Pizza
    114 {
    115     public override void prepare()
    116     {
    117         Console.WriteLine("伦敦的芝士披萨准备中");
    118     }
    119 }
    120 
    121 internal class LDGreekPizza : Pizza
    122 {
    123     public override void prepare()
    124     {
    125         Console.WriteLine("伦敦的希腊披萨准备中");
    126     }
    127 }
    view code

      工厂方法模式的优缺点:

        1、让父类的实现延迟到子类中去,减少判断。

        2、换汤不换药,和简单工厂模式类似,一般适用于产品对象相对较少,且产品固定的需求。

        3、工厂方法一定程度上减轻了工厂的职责,将职责细化,避免工厂类无法正常运行而导致程序崩溃。

    参考:https://www.jianshu.com/p/38493eb4ffbd 

  • 相关阅读:
    Codeforces Round#410 Div.2
    AtCoder Beginner Contest-060
    如何将gedit变成c++编译器
    洛谷 P2486 [SDOI2011]染色
    让lu哥头痛了许久的代码(洛谷:树的统计)
    字符串模拟入门
    luogu P1553 数字反转(升级版)
    那些令人难忘的——坑
    luogu P1341 无序字母对
    最短路相关题目
  • 原文地址:https://www.cnblogs.com/az4215/p/11516734.html
Copyright © 2020-2023  润新知