C#设计模式之二工厂方法模式(Factory Method Pattern)【创建型】

原文:C#设计模式之二工厂方法模式(Factory Method Pattern)【创建型】

一、引言

       在上一篇文章中我们讲解了过渡的一种模式叫做【简单工厂】,也有叫【静态工厂】的,通过对简单工厂模式得了解,我们也发现了它的缺点,就是随着需求的变化我们要不停地修改工厂里面的方法的代码,需求变化越多,里面的If--Else--也越多,这样就会造成简单工厂的实现逻辑过于复杂。设计模式是遵循一定原则而得来的,比如,我们要怎么增加代码,怎么修改代码,不是想怎么来就怎么来的,其中一个原则就是OCP原则,中文是【开放关闭原则】,对增加代码开发,对修改代码关闭,所以我们就不能总是这样修改简单工厂里面的方法。本章介绍的工厂方法模式可以解决简单工厂模式中存在的这个问题,下面就具体看看工厂方法模式是如何解决该问题的。


二、工厂方法模式的胡介绍

      2.1、动机(Motivate)

           在软件系统的构建过程中,经常面临着“某个对象”的创建工作:由于需求的变化,这个对象(的具体实现)经常面临着剧烈的变化,但是它却拥有比较稳定的接口

      如何应对这种变化?如何提供一种“封装机制”来隔离出“这个易变对象”的变化,从而保持系统中“其他依赖对象的对象”不随着需求改变而改变?

      2.2、意图(Intent)

         
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。                                        --《设计模式》GoF

      2.3、结构图(Structure)

           C#设计模式之二工厂方法模式(Factory Method Pattern)【创建型】

     2.4、模式的组成

          可以看出,在工厂方法模式的结构图有以下角色:

          (1)、抽象工厂角色(Creator):
充当抽象工厂角色,定义工厂类所具有的基本的操作,任何具体工厂都必须继承该抽象类。

          (2)、具体工厂角色(ConcreteCreator):充当具体工厂角色,该类必须继承抽象工厂角色,实现抽象工厂定义的方法,用来创建具体产品。

          (3)、抽象产品角色(Product):充当抽象产品角色,定义了产品类型所有具有的基本操作,具体产品必须继承该抽象类。

          (4)、具体产品角色(ConcreteProduct):充当具体产品角色,实现抽象产品类对定义的抽象方法,由具体工厂类创建,它们之间有一一对应的关系。

     2.5、工厂方法模式的代码实现

         【简单工厂模式】的问题是:如果有新的需求就需要修改工厂类里面创建产品对象实例的那个方法的实现代码,在面向对象设计一个原则就是哪里有变化,我就封装哪里。还有另外两个大的原则,其一是:面向抽象编程,细节和高层实现都要依赖抽象,第二个原则是:多组合,少继承。这三个原则是最根本的原则,学习设计模式必须以这三个原则为基点,否则都是枉然。根据这三大原则又衍生出来6个具体的原则,分别是【单一职责原则】,【里氏替换原则】,【依赖倒置原则】,【接口隔离原则】、【迪米特法则】和【开闭原则】,既然工厂类有变化,我们就封装它,面向抽象编程,我们先抽象出一个工厂基类,然后,每个需求就实现一个具体的工厂类,这样我们就符合了【开闭原则OCP】,让一个工厂生产一款产品,并一一对应。我们把具体产品的创建推迟到子类中,此时工厂类(这类是基类了)不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式就可以允许系统不修改工厂类逻辑的情况下来添加新产品,这样也就克服了简单工厂模式中缺点。下面就是工厂方法模式的实现代码:

C#设计模式之二工厂方法模式(Factory Method Pattern)【创建型】
 2 namespace 设计模式之工厂方法模式
 3 {
 4     /// <summary>
 5     /// 汽车抽象类
 6     /// </summary>
 7     public abstract class Car
 8     {
 9         // 开始行驶
10         public abstract void Go();
11     }
12 
13     /// <summary>
14     /// 红旗汽车
15     /// </summary>
16     public class HongQiCar : Car
17     {
18         public override void Go()
19         {
20             Console.WriteLine("红旗汽车开始行驶了");
21         }
22     }
23 
24     /// <summary>
25     /// 奥迪汽车
26     /// </summary>
27     public class AoDiCar : Car
28     {
29         public override void Go()
30         {
31             Console.WriteLine("奥迪汽车开始行驶了");
32         }
33     }
34 
35     /// <summary>
36     /// 抽象工厂类
37     /// </summary>
38     public abstract class Factory
39     {
40         // 工厂方法
41         public abstract Car CreateCar();
42     }
43 
44     /// <summary>
45     /// 红旗汽车工厂类
46     /// </summary>
47     public class HongQiCarFactory:Factory
48     {
49         /// <summary>
50         /// 负责生产红旗汽车
51         /// </summary>
52         /// <returns></returns>
53         public override Car CreateCar()
54         {
55             return new HongQiCar();
56         }
57     }
58 
59     /// <summary>
60     /// 奥迪汽车工厂类
61     /// </summary>
62     public class AoDiCarFactory:Factory
63     {
64         /// <summary>
65         /// 负责创建奥迪汽车
66         /// </summary>
67         /// <returns></returns>
68         public override Car CreateCar()
69         {
70             return new AoDiCar();
71         }
72     }
73 
74     /// <summary>
75     /// 客户端调用
76     /// </summary>
77     class Client
78     {
79         static void Main(string[] args)
80         {
81             // 初始化创建汽车的两个工厂
82             Factory hongQiCarFactory = new HongQiCarFactory();
83             Factory aoDiCarFactory = new AoDiCarFactory();
84 
85             // 生产一辆红旗汽车
86             Car hongQi = hongQiCarFactory.CreateCar();
87             hongQi.Go();
上一篇:windows系列的(xp/win7/server2003/2008/2012...)完美移植到centos7下面的虚拟机(KVM)


下一篇:cf869 E. The Untended Antiquity(二维树状数组,随机数)