C#之三十八 简单工厂设计模式(下)

简介: C#之三十八 简单工厂设计模式(下)

4.9、模式实现


    我们通过上面的分析,已经清晰的知道了工厂模式中的各种角色和职责,那工厂模式通过代码是怎么实现的呢?OK,下面将继续分析上面的吃早餐中的故事,做一个简单的示例实现。


    1、首先我们来看看只有一个产品对象的简单工厂模式的实现。其实这很好理解,就当店里只卖一种食品,这里以馒头为例。


1 /// 
 2 /// 馒头
 3 /// 
 4 public class SteamedBread
 5 {
 6     /// 
 7     /// 构造方法
 8     /// 
 9     public SteamedBread()
10     { }
11 
12     /// 
13     /// 销售价格
14     /// 
15     private double price=0.5;
16     public double Price
17     {
18         get { return price; }
19         set { price = value; }
20     }
21 }


 


    OK,产品对象建立好了,下面就是创建工厂(Factory)对象了。


1 /// 
 2 /// 工厂角色
 3 /// 
 4 public class Factory
 5 {
 6     /// 
 7     /// 创建一个馒头(SteamedBread)对象
 8     /// 
 9     /// 
10     public static SteamedBread CreateInstance()
11     {
12         return new SteamedBread();
13     }
14 }

    此时,客户端可以这样来调用:


1 public class Client
2 {
3     public static void Main(string[] args)
4     {
5         //通过工厂创建一个产品的实例
6         SteamedBread sb = Factory.CreateInstance();
7         Console.WriteLine("馒头{0}元一个!", sb.Price);
8     }
9 }

    如上就完成了一个简单工厂模式的简单实现,一个产品和一个工厂,工厂负责创建这个产品。但是者种实现有一定的缺陷,为每一种产品创建一个静态方法来完成产品对象的创建,如果有多个产品则需要定义多个静态方法分别返回不同的对象,用设计原则来说的话这样的实现不符合依赖倒置原则(DIP)。如果系统里只有一个单独的产品对象,那么采用这种实现是完全可以的。UML图如下:


2、带抽象产品(AbstractProduct)角色的简单工厂模式实现


    从上面分析中得知,这种实现得为每一种产品创建一个静态方法来完成产品对象的创建。虽然带有简单工厂的性质,但是又好象不能够完全体现出简单工厂模式的意图。简单工厂的意图是:根据提供给他的数据,返回几个可能类中的一个类的实例。根据意图出发进行分析,要实现完全满足简单工厂模式意图的程序,也就得根据提供给工厂的数据,让工厂根据这个数据来进行判断,然后返回相应的对象。OK,看看是下面这样的吗?


8     /// 由于我们只需要得到价格,所以这里就只提供get属性访问器
 9     /// 
10     double price{get;}
11 }
12 ------------------------------------------------------------------------------------
13 /// 
14 /// 馒头
15 /// 
16 public class SteamedBread:IFood
17 {
18     /// 
19     /// 构造方法
20     /// 
21     public SteamedBread()
22     { }
23 
24     public double price
25     {
26         get
27         {
28             return  0.5;
29         }
30     }
31 }
32 ------------------------------------------------------------------------------------
33 /// 
34 /// 包子
35 /// 
36 public class SteamedStuffed:IFood
37 {
38     public SteamedStuffed()
39     { }
40 
41     /// 
42     /// 销售价格
43     /// 
44     public double price
45     {
46         get
47         {
48             return  0.6;  //0.6元一个
49         }
50     }
51 }
52 ------------------------------------------------------------------------------------
53 /// 
54 /// 工厂角色
55 /// 
56 public class Factory
57 {
58     /// 
59     /// 创建一个馒头(SteamedBread)对象
60     /// 
61     /// 
62     public static IFood CreateInstance(string key)
63     {
64         if (key == "馒头")
65         {
66             return new SteamedBread();
67         }
68         else
69         {
70             return new SteamedStuffed();
71         }
72     }
73 }
74 ------------------------------------------------------------------------------------
75 public class Client
76 {
77     public static void Main(string[] args)
78     {
79         //通过工厂创建一个产品的实例
80         IFood food = Factory.CreateInstance("馒头");
81         Console.WriteLine("馒头{0}元一个!", food.price);
82 
83         food = Factory.CreateInstance("包子");
84         Console.WriteLine("包子{0}元一个!", food.price);
85     }
86 }


    此时的设计就已经完全符合简单工厂模式的意图了。顾客(Client)对早餐店营业员(Factory)说,我要“馒头”,于是营业员便根据顾客所提供的数据(馒头),去众多食品中找,找到了然后就拿给顾客。


    3、模式的演变实现


    有些情况下Simple Factory可以由抽象产品角色扮演,一个抽象产品类同时是子类的工厂。也就是说,抽象产品角色扮演两种角色和职责,出了基本的定义还还兼任工厂角色的职责,负责产品的创建工作。这里我们在上面的例子基础上适当修改一下OK了,新建立一个抽象类(Evolution):


1 /// 
 2 /// 兼任抽象产品角色和工厂角色两种角色
 3 /// 
 4 public abstract class Evolution
 5 {
 6     /// 
 7     /// 共性字段
 8     /// 
 9     private double price;
10     public double Price
11     {
12         get { return price; }
13         set { price = value; }
14     }
15 
16 
17     public static Evolution CreateInstance(string key)
18     {
19         if (key == "馒头")
20         {
21             return new SteamedBread();
22         }
23         else
24         {
25             return new SteamedStuffed();
26         }
27     }
28 }


    那现在,具体的产品对象的设计也应该修改了,把原来实现于IFood接口改为继承此抽象类,如下:


1 public class SteamedBread : Evolution
 2 {
 3     public SteamedBread()
 4     {
 5         this.Price = 0.5; //在构造方法里初始话属性的值
 6     }
 7 }
 8 
 9 public class SteamedStuffed : Evolution
10 {
11     public SteamedStuffed()
12     {
13         this.Price = 0.6;
14     }
15 }

 


    通过上面的演化,此时客户端的调用如下:


1 public class Client

2 {

3     public static void Main(string[] args)

4     {

5         Evolution el = Evolution.CreateInstance("包子");

6         Console.WriteLine("包子{0}元一个!", el.Price);

7     }

8 }


    UML草图如下:


如果抽象产品角色省略,那么工厂角色就可以与具体产品角色合并。也就是说一个产品类就是自身的工厂。这样把原有三个独立的角色:抽象产品角色、具体产品角色和工厂角色合并为一个,这个类自己负责创建自己的实例。


    注:以上演变可以从上面的程序代码中直接修改而来,这里我就不贴代码了。  


4.10、模式优缺点


     工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅"消费"产品。简单工厂模式通过这种做法实现了对责任的分割。


     当产品有复杂的多层等级结构时,工厂类只有自己,以不变应万变,就是模式的缺点。因为工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。


     系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,有可能造成工厂逻辑过于复杂,违背了"开放--封闭"原则(OCP).另外,简单工厂模式通常使用静态工厂方法,这使得无法由子类继承,造成工厂角色无法形成基于继承的等级结构。


4.11、相关模式


     工厂方法模式:每个产品由一个专门的工厂来负责创建。是一种只有唯一一个产品的实现,带有简单工厂的性质。


     抽象工厂模式:大致和工厂方法相同。


     单例模式:单例的实现和上面模式演变中的最后一种很相似,只要把构造器私有便OK。


目录
相关文章
|
1月前
|
设计模式 Java 数据库
小谈设计模式(2)—简单工厂模式
小谈设计模式(2)—简单工厂模式
|
1月前
|
设计模式 Java PHP
php设计模式--简单工厂模式(一)
php设计模式--简单工厂模式(一)
18 0
|
1月前
|
设计模式
设计模式-简单工厂和工厂方法
设计模式-简单工厂和工厂方法
|
1天前
|
设计模式 Java
Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)
Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)
6 2
|
6天前
|
设计模式 Java 编译器
设计模式——创建型模式(工厂,简单工厂,单例,建造者,原型)
设计模式——创建型模式(工厂,简单工厂,单例,建造者,原型)
|
19天前
|
设计模式 XML Java
【设计模式】第三篇:一篇搞定工厂模式【简单工厂、工厂方法模式、抽象工厂模式】
三 结尾 如果文章中有什么不足,欢迎大家留言交流,感谢朋友们的支持! 如果能帮到你的话,那就来关注我吧!如果您更喜欢微信文章的阅读方式,可以关注我的公众号
21 5
|
1天前
|
设计模式 C#
技术经验分享:C#设计模式
技术经验分享:C#设计模式
|
2天前
|
设计模式
简单工厂模式-大话设计模式
简单工厂模式-大话设计模式
5 0
|
1月前
|
设计模式 uml
【设计模式】一文搞定简单工厂模式!
【设计模式】一文搞定简单工厂模式!
20 2
|
1月前
|
设计模式 算法
设计模式思考,简单工厂模式和策略模式的区别?
设计模式思考,简单工厂模式和策略模式的区别?