简单工厂、工厂方法、抽象工厂

一、简单工厂 

实现如下:

 1     //计算器总的抽象类
 2     public abstract class Computer
 3     {
 4         private int _NumberA;
 5         private int _NumberB;
 6         public int NumberA
 7         {
 8             set {
 9                 _NumberA = value;
10             }
11             get
12             {
13                 return _NumberA;
14             }
15         }
16 
17         public int NumberB
18         {
19             set
20             {
21                 _NumberB = value;
22             }
23             get
24             {
25                 return _NumberB;
26             }
27         }
28 
29         public abstract int Result
30         {
31             get;
32         }
33     }
34     //加法计算器类
35     public class JiaComputer:Computer
36     {
37 
38         public override int Result
39         {
40             get { return base.NumberA + base.NumberB; }
41         }
42     }
43     //减法计算器类
44     public class JianComouter : Computer
45     {
46         public override int Result
47         {
48             get { return base.NumberA - base.NumberB; }
49         }
50     }
51     //乘法计算器类
52     public class ChenComputer : Computer
53     {
54         public override int Result
55         {
56             get { return base.NumberA * base.NumberB; }
57         }
58     }
59     //除法计算器类
60     public class ChuComputer : Computer
61     {
62         public override int Result
63         {
64             get { return base.NumberA / base.NumberB; }
65         }
66     }
计算器类的实现

在主函数中调用的代码如下:

 1             Console.WriteLine("请输入第一个数字");
 2             int a = int.Parse(Console.ReadLine());
 3             Console.WriteLine("请输入第二个数字!");
 4             int b = int.Parse(Console.ReadLine());
 5             Console.WriteLine("请输入操作符");
 6             string op = Console.ReadLine();
 7 
 8             int result = 0;
 9             //使用这种方法,重复性 很大,还有  如果增加了一个运算符的话  ,修改 用户层了,这样的耦合  太强了
10             switch (op)
11             {
12                 case "+":
13                     AddCompter com = new AddCompter();
14                     com.NumberA = a;
15                     com.NumberB = b;
16                     result = com.Result;
17                     break;
18                 case "-":
19                     AddCompter com2 = new AddCompter();
20                     com2.NumberA = a;
21                     com2.NumberB = b;
22                     result = com2.Result;
23                     break;
24                 case "*":
25                     AddCompter com3 = new AddCompter();
26                     com3.NumberA = a;
27                     com3.NumberB = b;
28                     result = com3.Result;
29                     break;
30                 case "/":
31                     AddCompter com4 = new AddCompter();
32                     com4.NumberA = a;
33                     com4.NumberB = b;
34                     result = com4.Result;
35                     break;
36 
37                 default:
38                     break;
39             }
主函数实现代码

使用简单工厂,将创建计算器的过程封装到工厂里面去,使用的时候直接从工厂中调用对应的方法直接调用就可以了;而且扩展的话很容易,因为将创建过程封装起来的,不需要修改客户端代码,增强代码的健壮性。

结构图: 

代码:

 1     public class SimFactory
 2     {
 3         //此方法将复杂度封装起来了,将创建和表示相分离。。用户不必知道内部是怎么实现的。。
 4         //这样不管在增加几个运算符的类,不管后期怎么扩展,只要实现抽象类Computer,只需要在此方法内增加一个就可以,,用户界面不许修改,将变化封装起来了。
 5         public static Computer GetCom(string op)
 6         {
 7             Computer com =null;
 8             switch (op)
 9             {
10                 case "+":
11                     com = new JiaComputer();
12                     break;
13                 case "-":
14                     com = new JianComouter();
15                     break;
16                 case "*":
17                     com = new ChenComputer();
18                     break;
19                 case "/":
20                     com = new ChuComputer();
21                     break;
22                 default:
23                     break;
24             }
25             return com;
26 
27         }
28     }
工厂函数

主函数调用代码:

            Console.WriteLine("请输入第一个数字");
            int a = int.Parse(Console.ReadLine());
            Console.WriteLine("请输入第二个数字!");
            int b = int.Parse(Console.ReadLine());
            Console.WriteLine("请输入操作符");
            string op = Console.ReadLine();

            int result = 0;
            //不管 在增加 几个运算类 ,用户层都不会更改
            Computer com = SimFactory.GetCom(op);
            com.NumberA = a;
            com.NumberB = b;

            result = com.Result;
            Console.WriteLine(result);

二、工厂方法

 简单工厂其不是设计模式,只是向工厂方法和抽象工厂的过度的一个过程。

出现原因:

1、在软件系统中,面临着一个对象的“创建工作”;由于需求的变化,这个复杂的对象经常发生剧烈的变化,但是却拥有稳定的创建接口。

2、如何应对这样的变化?如何提供一种“封装机制”来隔离出这个复杂对象的变化 ,从而是系统中依赖此对象的对象不会随着需求的变化而变化

意图:

 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。(将每个对象的创建延迟到每个对应的子工厂

结构图:

代码:

  1     //这种工厂方法的设计模式:1、全部都是对象之间的操作,创建产品的实例的时候都是在 对象的工厂里面创建的,而不是在过程中创建的,体现了面向对对象的思想  ,体现了封装性的原则(创建对象是在类的内部创建的)
  2     //2、将 对象的复杂度都在类内部进行处理了,降低的 耦合度。 
  3     //3、每个类只执行自己应该做的功能的并且只执行一个工能,体现的单一职责原则,还有迪米特原则,比如工厂就是 创建一个 工厂的实例,没做其他事情。一个子工厂值创建一个 对应的子产品,一个子产品运算符只执行一种运算工能。
  4 
  5 
  6     /// <summary>
  7     /// 最基层的工厂接口,,下面每种产品含有自己对应的一个工厂,在创建的时候找到自己对应的工厂通过FactoryMethod()方法创建就可以了
  8     /// </summary>
  9     public interface IFactory
 10     {
 11         //这个就是工厂方法:
 12         Computer GetFactoryMethod();
 13     }
 14 
 15     public class AddFactory : IFactory
 16     {
 17         public Computer GetFactoryMethod()
 18         {
 19             return new AddCompter();
 20         }
 21     }
 22 
 23     public class JianFactory : IFactory
 24     {
 25         public Computer GetFactoryMethod()
 26         {
 27             return new JianCompter();
 28         }
 29     }
 30 
 31     public class ChengFactory : IFactory
 32     {
 33         public Computer GetFactoryMethod()
 34         {
 35             return new ChenCompter();
 36         }
 37     }
 38 
 39     public class ChuFactory : IFactory
 40     {
 41         public Computer GetFactoryMethod()
 42         {
 43             return new ChuComputer();
 44         }
 45     }
 46 
 47 
 48 
 49     
 50 
 51     public abstract class Computer
 52     {
 53         private int _NumberA;
 54 
 55         public int NumberA
 56         {
 57             get { return _NumberA; }
 58             set { _NumberA = value; }
 59         }
 60         private int _NumberB;
 61 
 62         public int NumberB
 63         {
 64             get { return _NumberB; }
 65             set { _NumberB = value; }
 66         }
 67 
 68         public string op { set; get; }
 69         public abstract int Result
 70         {
 71             get;
 72         }
 73     }
 74 
 75 
 76     public class AddCompter : Computer
 77     {
 78 
 79         public override int Result
 80         {
 81             get
 82             {
 83                 return base.NumberA + base.NumberB;
 84             }
 85         }
 86     }
 87 
 88     public class JianCompter : Computer
 89     {
 90         public override int Result
 91         {
 92             get
 93             {
 94                 return base.NumberA - base.NumberB;
 95             }
 96         }
 97     }
 98 
 99 
100     public class ChenCompter : Computer
101     {
102         public override int Result
103         {
104             get
105             {
106                 return base.NumberA * base.NumberB;
107             }
108         }
109     }
110 
111     public class ChuComputer : Computer
112     {
113         public override int Result
114         {
115             get
116             {
117                 if (base.NumberB != 0)
118                 {
119                     return base.NumberA / base.NumberA;
120                 }
121                 else
122                 {
123                     throw new Exception("除数不能为0!");
124                 }
125             }
126         }
127     }
128 }
工厂方法版的计算器版

主函数调用:

 1             Console.WriteLine("请输入第一个数字");
 2             int a = int.Parse(Console.ReadLine());
 3             Console.WriteLine("请输入第二个数字!");
 4             int b = int.Parse(Console.ReadLine());
 5             Console.WriteLine("请输入操作符");
 6             string op = Console.ReadLine();
 7 
 8             int result = 0;
 9             IFactory factory = null;
10             Computer com = null;
11             switch (op)
12             {
13                 case "+":
14                     factory = new AddFactory();
15                     break;
16                 case "-":
17                     factory = new JianFactory();
18                     break;
19                 case "*":
20                     factory = new ChengFactory();
21                     break;
22                 case "/":
23                     factory = new ChuFactory();
24                    
25                     break;
26                 default:
27                     break;
28             }
29             com = factory.GetFactoryMethod();
30             com.NumberA = a;
31             com.NumberB = b;
32             result = com.Result;
33             Console.WriteLine(result);
34             Console.ReadKey();
主函数调用

作用:

Factory Method模式的两种情况:一是Creator类是一个抽象类且它不提供它所声明的工厂方法的实现使用抽象实现的多态);二是Creator是一个具体的类且它提供一个工厂方法的缺省实现(使用的不是抽象,使用的virtual实现的多态)。

 

工厂方法是可以带参数的。 (比如:获得产品的时候,想要获得其他的一下额外的信息(例如:获得订单类的时候,想要 查出指定的订单,将订单的 编号传进去))

 

工厂的作用并不仅仅只是创建一个对象,它还可以做对象的初始化,参数的设置等。

效果:

1用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。 (产品的创建是在对应的子类的工厂里面创建的,体现了面向对象,体现了“封装性”原则

2Factory Method模式通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类(子工厂),从而提供了一种扩展的策略多一个产品就对应多一个工厂),较好的解决了这种紧耦合的关系(创建每一个产品的实例都是在对应的子工厂里面创建的。这样耦合度就大大降低了,  场频那方面更改之后,用户操作 就几乎不用更改。将修改封装

适用性:

1. 当一个类不知道它所必须创建的对象的类的时候。 比如:用户要进行运算操作,但是用户不知道用哪一种运算,所以就要将变化封装起来,创建过程用户是不知道的

2. 当一个类希望由它的子类来指定它所创建的对象的时候。 就是将创建对象初始化的工作交给子工厂

3. 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。 

总结:

1Factory Method模式主要用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系会导致软件的脆弱。

 

2Factory Method模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展而非更改)的策略,较好地解决了这种紧耦合关系。

三、抽象工厂

出现原因:

1、经常出现创建一系列产品。如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合(怎么降低耦合度:将创建实例延迟到 对应的产品系列的 接口去创建)

 

2、主要针对的 多种产品的多个系列,注意每个系列之间的产品必须是有依赖性、有关联性的

意图:

提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。(一个系列的产品对应一个对应抽象基工厂,创建这个系列中的不同种产品

结构图:

 

代码:

 1     //创建两种系列的产品(1、2为系列),每个系列中都有两种产品(A、B两种)
 2     //定义两种产品
 3     public interface IProductA
 4     {
 5 
 6     }
 7 
 8     public interface IProductB
 9     {
10     }
11 
12     //下面是一种产品的几种类型
13     public class ProductA1:IProductA
14     {
15     }
16 
17     public class ProductA2 : IProductA
18     {
19     }
20 
21     public class ProductB1 : IProductB
22     {
23     }
24 
25     public class ProductB2 : IProductB
26     {
27     }
28 
29 
30     //下面创建工厂:是针对 系列 进行 创建的
31     public interface IAbsFactory
32     {
33         IProductA CreateProductA();
34         IProductB CreateProductB();
35     }
36 
37     public class  Factory1:IAbsFactory
38     {
39         public IProductA CreateProductA()
40         {
41             return new ProductA1();
42         }
43 
44         public IProductB CreateProductB()
45         {
46             return new ProductB1();
47         }
48     }
49 
50 
51     public class Factory2 : IAbsFactory
52     {
53         public IProductA CreateProductA()
54         {
55             return new ProductA2();
56         }
57 
58         public IProductB CreateProductB()
59         {
60             return new ProductB2();
61         }
62     }
抽象工厂

主函数调用:

 1             IProductA productA = null;
 2             IProductB productB = null;
 3             IAbsFactory factory = null;
 4             //为两种产品创建 创建地中类型的 产品
 5             factory = new Factory1();
 6             productA = factory.CreateProductA();
 7             productB = factory.CreateProductB();
 8             //创建第二种类型的产品
 9             factory = new Factory2();
10             productA = factory.CreateProductA();
11             productB = factory.CreateProductB();
12             //在实际项目中,上面的工厂是通过反射动态创建的。

实现要点:

1、抽象工厂将产品对象的创建延迟到它的具体工厂的子类。 

 

2、通常在运行时刻创建一个具体工厂类的实例(通过反射动态创建),这一具体工厂的创建具有特定实现的产品对象,为创建不同的产品对象,客户应使用不同的具体工厂。 (一个系列产品对应创建一个工厂,进而通过工厂创建不同种的产品)

 

3、把工厂作为单件,一个应用中一般每个产品系列只需一个具体工厂的实例,因此,工厂通常最好实现为一个单件模式。 

 

4、创建产品,抽象工厂仅声明一个创建产品的接口真正创建产品是由具体工厂类创建的(封装原则),最通常的一个办法是为每一个产品定义一个工厂方法,一个具体的工厂将为每个产品重定义该工厂方法以指定产品,虽然这样的实现很简单,但它要求每个产品系列都要有一个新的具体工厂子类,即使这些产品系列的差别很小。(每个系列都要有一个 工厂的子类 与之对应,并且,每种产品在 工厂里面 都会有与之对应的 一个工厂方法进行创建 他们) 

适用性:

 1一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。(应该尽量降低耦合度

 

2、这个系统有多于一个的产品族,而系统只消费其中某一产品族。(有多个系列产品,但是系统只会使用其中的一个,将这些产品进行切换使用)

 

3同属于同一个产品族的产品是在一起使用的(就是同一系列的产品 之间要有联系、有依赖,需要同时使用。(不要停留在所举的例子:不同品牌的帽子、鞋,这只是为了理解),真正使用的时候同一系列产品之间是用联系的),这一约束必须在系统的设计中体现出来。

 

4、系统提供一个产品类的库,所有的产品以同样的接口出现(工厂接口下面的具体工厂子类可以创建这个系列的所有产品),从而使客户端不依赖于实现

总结:

1、如果没有应对“多系列对象构建”(多种产品的多个系列)的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的静态工厂完全可以

 

2 系列对象”指的是这些对象之间有相互依赖、或作用的关系,例如游戏开发场景中的“道路”与“房屋”的依赖,“道路”与“地道”的依赖。

 

 (*)3Abstract Factory模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动(抽象工厂 优势对 新的系列 产品 扩展是非常方便缺点:但是如果要扩展产品的种类,那就shit了,完全乱了,这个时候就要对 工厂就行修改了,因为所有系列的工厂都要修改违反了开闭原则)

 

 4Abstract Factory模式经常和Factory Method模式共同组合来应对“对象创建”的需求变化(搭建的那个 项目架构就是组合使用,由一个工厂 统一 生产一系列的产品,这些产品是通过工厂方法模式创建出来(使用 反射动态创建)

四、总结

1、Builder模式解决对象部分”的需求变化,Factory Method模式解决“单个对象”的需求变化,Abstract Factory 模式解决“系列对象”的需求变化。

 

2、如果不是多个系列的产品的创建,使用简单的静态工厂就可以了。

原文地址:https://www.cnblogs.com/xiaoxiaogogo/p/3579197.html