浅谈简单工厂,工厂方法,抽象工厂的使用

前言

这几天了解了工厂模式,自己也整理下思路,任何一种模式的出现都是为了让我们的程序有更好的可扩展性,工厂模式也不例外。

简单工厂

在实际的代码coding中我们在创建对象(也就是实例化一个类)的时候往往需要new class()这样来操作。举个例子:

这是项目结构

 

 
//这是一个中国人的类
public class ChinesePepole { public void Show() { Console.WriteLine("I'm a {0}", this.GetType().Name); } }

当我们在前端(这里是在控制台)需要使用的时候就一般会这样做 

1   static void Main(string[] args)
2         {
3             //创建一个中国人
4             ChinesePepole chinesePepole = new ChinesePepole();
5             chinesePepole.Show();
6             
7         }     

这样做显然不利于程序扩展,比如这里创建对象我们要换成一个美国人,日本人我们要不断的去修改代码。

 1     static void Main(string[] args)
 2         {
 3             //创建一个中国人
 4             ChinesePepole chinesePepole = new ChinesePepole();
 5             chinesePepole.Show();
 6             //创建一个美国人
 7             AmericanPeople americanPeople = new AmericanPeople();
 8             americanPeople.Show();
 9             //创建一个日本人
10             JapanesePeople japanesePeople = new JapanesePeople();
11             japanesePeople.Show();
12 
13             Console.ReadLine();
14             
15         }    

 

因为违背了面向对象设计的依赖倒置原则,这里解释下什么是依赖倒置原则

依赖倒置原则

A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。

B.抽象不应该依赖于具体实现,具体实现应该依赖于抽象。

说的简单点就是我们的上层模块不应该出现类名ChinesePeople和new class()这样的细节。好那这里我们先引入接口
 1     /// <summary>
 2     /// 把人进行抽象 定义一个接口 
 3     /// </summary>
 4     public interface IPeople
 5     {
 6         void Show();
 7     }
 8 
 9  /// <summary>
10     /// 具体的人 中国人
11     /// </summary>
12     public class ChinesePepole : IPeople
13     {
14         public void Show()
15         {
16             Console.WriteLine("I'm a {0}", this.GetType().Name);
17         }
18     }
19 
20 /// <summary>
21     /// 具体的人 美国人
22     /// </summary>
23     public class AmericanPeople : IPeople
24     {
25         public void Show()
26         {
27             Console.WriteLine("I'm a {0}", this.GetType().Name);
28         }
29     }
30 
31     /// <summary>
32     /// 具体的人 日本人
33     /// </summary>
34     public class JapanesePeople : IPeople
35     {
36         public void Show()
37         {
38             Console.WriteLine("I'm a {0}", this.GetType().Name);
39         }
40     }

这时我就可以通过接口来创建对象了

 1 static void Main(string[] args)
 2         {
 3           
 4                 //创建一个中国人
 5                 IPeople chinesePepole = new ChinesePepole();
 6                 chinesePepole.Show();           
 7             
 8             Console.ReadLine();
 9 
10         }     

这时虽然左边没有的具体的类名 ,但右边依然有new class()这样的细节,这时工厂就出现了,就是把实例化对象的过程交给工厂来处理。简单工厂代码如下:

 1 public class Factory
 2     {
 3         public IPeople.IPeople GetPeople(PeopleType peopleType)
 4         {
 5             switch (peopleType)
 6             {
 7                 case PeopleType.Chinese:
 8                     return new ChinesePepole();
 9                 case PeopleType.American:
10                     return new AmericanPeople();
11                 case PeopleType.Japanese:
12                     return new JapanesePeople();
13                 default:
14                     throw new Exception("没有可用的类");
15             }
16         }
17 
18         public enum PeopleType
19         {
20             Chinese,
21             American,
22             Japanese
23         }
24     }

上层调用

1   static void Main(string[] args)
2         {          
3             Factory factory = new Factory();
4             //创建一个中国人
5             IPeople.IPeople chinesePeople = factory.GetPeople(Factory.PeopleType.Chinese);
6             chinesePeople.Show();
7             Console.ReadLine();
8         }  

简单工厂就是这样,调用工厂类根据上层传入的参数创建我们需要的实例类。

简单工厂的优点和缺点

优点:能够根据外界给定的信息自动去创建对象,上层没有具体创建类的细节,提高了程序的可扩展性

缺点:工厂类集中了所有实例的创建逻辑,程序中创建对象的细节并没有消失,我们只是转移了细节。如果要新增实体对象的创建还是要修改程序,违背了开-闭原则 (对扩展开放,对修改关闭)。

工厂方法

介绍:

工厂方法就是对上面的简单工厂进行升级,不让所有实例的创建逻辑都在一个工厂类中实现,具体的类交给具体的工厂去创建。

核心代码如下:

1 /// <summary>
2     /// 抽象工厂类
3     /// </summary>
4     public interface IFactory
5     {
6         IPeople.IPeople CreatePeople();
7     }
 1  /// <summary>
 2     /// 具体工厂类: 用于创建中国人类
 3     /// </summary>
 4     public class ChineseFactory : IFactory
 5     {
 6         public IPeople.IPeople CreatePeople()
 7         {
 8             return new ChinesePepole();
 9         }
10     }
 1 /// <summary>
 2     /// 具体工厂类: 用于创建美国人类
 3     /// </summary>
 4     public class AmericanFactory:IFactory
 5     {
 6         public IPeople.IPeople CreatePeople()
 7         {
 8             return new People.AmericanPeople();
 9         }
10     }
 //上层调用
static void Main(string[] args) { IFactory factory = new AmericanFactory(); IPeople.IPeople americanPeople = factory.CreatePeople(); americanPeople.Show(); Console.ReadLine(); }

 

工厂方法的优点和缺点

优点:具体的类交给具体的工厂去创建,符合开闭原则,如果再新建一个类,只需要新增对应的工厂类即可,不需要对代码进行修改。

缺点:代码多,新增了一个工厂类(呵呵)

抽象工厂

代码如下

抽象工厂代码

 1 /// <summary>
 2     /// 抽象工厂类
 3     /// </summary>
 4     public abstract class AbstractFactory
 5     {
 6         /// <summary>
 7         /// 抽象方法:创建一个人
 8         /// </summary>
 9         /// <returns></returns>
10         public abstract AbstractPeople CreatePeople();
11 
12         /// <summary>
13         /// 抽象方法:创建一辆车
14         /// </summary>
15         /// <returns></returns>
16         public abstract AbstractCar CreateCar();
17     }

具体工厂代码

 1  /// <summary>
 2     /// 具体工厂类 创建一个美国的工厂
 3     /// </summary>
 4     public class AmericanFactory : AbstractFactory
 5     {
 6         public override AbstractPeople CreatePeople()
 7         {
 8             return new AmericanPeople();
 9         }
10 
11         public override AbstractCar CreateCar()
12         {
13             return new AmericanCar();
14         }
15     }
16 
17 /// <summary>
18     /// 具体工厂类 创建一个中国的工厂
19     /// </summary>
20     public class ChineseFactory : AbstractFactory
21     {
22         public override AbstractPeople CreatePeople()
23         {
24             return new ChinesePepole();
25         }
26 
27         public override AbstractCar CreateCar()
28         {
29             return new ChineseCar();
30         }
31     }

具体实例的代码

  1 /// <summary>
  2     /// 具体的人 美国人
  3     /// </summary>
  4     public class AmericanPeople : AbstractPeople
  5     {
  6         /// <summary>
  7         /// 国家
  8         /// </summary>
  9         public override string Country
 10         {
 11             get
 12             {
 13                 return "美国";
 14             }
 15         }
 16 
 17         /// <summary>
 18         /// 爱好
 19         /// </summary>
 20         public override string Like
 21         {
 22             get
 23             {
 24                 return "打蓝球";
 25             }
 26         }
 27 
 28         /// <summary>
 29         /// 肤色
 30         /// </summary>
 31         public override string Color
 32         {
 33             get
 34             {
 35                 return "白种人";
 36             }
 37         }
 38     }
 39 
 40 /// <summary>
 41     /// 具体的人 中国人
 42     /// </summary>
 43     public class ChinesePepole :AbstractPeople
 44     {
 45         /// <summary>
 46         /// 国家
 47         /// </summary>
 48         public override string Country
 49         {
 50             get
 51             {
 52                 return "中国";
 53             }
 54         }
 55 
 56         /// <summary>
 57         /// 爱好
 58         /// </summary>
 59         public override string Like
 60         {
 61             get
 62             {
 63                 return "打乒乓球";
 64             }
 65         }
 66 
 67         /// <summary>
 68         /// 肤色
 69         /// </summary>
 70         public override string Color
 71         {
 72             get
 73             {
 74                 return "黄种人";
 75             }
 76         }
 77     }
 78 
 79 /// <summary>
 80     /// 具体的车 美国人的车
 81     /// </summary>
 82     public class AmericanCar : AbstractCar
 83     {
 84         /// <summary>
 85         /// 类型
 86         /// </summary>
 87         public override string Type
 88         {
 89             get
 90             {
 91                 return "商务车";
 92             }
 93         }
 94 
 95         /// <summary>
 96         /// 颜色
 97         /// </summary>
 98         public override string Color
 99         {
100             get
101             {
102                 return "红色";
103             }
104         }        
105     }
106 
107 /// <summary>
108     /// 具体的车 中国人的车
109     /// </summary>
110     public class ChineseCar : AbstractCar
111     {
112         /// <summary>
113         /// 类型
114         /// </summary>
115         public override string Type
116         {
117             get
118             {
119                 return "越野车";
120             }
121         }
122 
123         /// <summary>
124         /// 颜色
125         /// </summary>
126         public override string Color
127         {
128             get
129             {
130                 return "黑色";
131             }
132         }        
133     }

上层调用

 1 static void Main(string[] args)
 2         {
 3             //CreateObject o = new CreateObject(new AmericanFactory());
 4             //o.ReadyInfo();
 5             CreateObject o = new CreateObject(new ChineseFactory());
 6             o.ReadyInfo();
 7             Console.ReadLine();
 8         }
 9 
10         /// <summary>
11         /// 创建对象
12         /// </summary>
13         public class CreateObject
14         {
15             private AbstractPeople people;
16             private AbstractCar car;
17 
18             public CreateObject(AbstractFactory.AbstractFactory factory)
19             {
20                 people = factory.CreatePeople();
21                 car = factory.CreateCar();
22             }
23 
24             public void ReadyInfo()
25             {
26                 Console.WriteLine(string.Format("我是一个{0},来自{1},喜欢开着{2}的{3}。",
27                     people.Color,
28                     people.Country,
29                     car.Color,
30                     car.Type
31                     ));
32             }
33         }

抽象工厂的优点/缺点: 

优点:

    抽象工厂模式封装了具体类的创建,

    当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象,

    增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。

缺点:增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类

总结:

简单工厂:一个工厂创建多个类 分支
工厂方法:一个工厂创建一个类
抽象工厂:一个工厂创建多个类 适用于产品簇

posted @ 2017-05-08 14:58  一叶青城  阅读(190)  评论(0编辑  收藏  举报