欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-03 16:41:37
工厂设计模式: 顾名思义,该模式是用来生产对象的。在面向对象的设计模式中,万物皆对象,若使用new来创建对象,就会对该对象产生强耦合,加入我们需要更换该对象,那么使用该对象的对象都需要进行修改,这显然违背了开闭原则(OCP)。如果我们使用工厂来产生对象,我们只需要与这个工厂打交道就可以了,无需关心具 ......

工厂设计模式:

  顾名思义,该模式是用来生产对象的。在面向对象的设计模式中,万物皆对象,若使用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 }

  传统模式的优缺点:

    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 }

  简单工厂模式优缺点:

    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 }

  工厂方法模式的优缺点:

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

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

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

参考: