工厂模式

工厂模式理论我不长篇大论了。其核心功能是根据“需求”生产“产品”,设计模式的核心是解耦。工厂模式就是为了解耦“需求”和“产品”,但是别忘了,工厂模式工厂模式,还有一个重要元素,就是“工厂”,所以工厂模式的核心思想,就是解耦“需求”“工厂”和“产品”。

 

工厂模式,实际上也会根据业务情景不同会有不同的实现方式。一般分为3种。简单工厂,工厂和抽象工厂

关键点:

一、三种工厂的实现是越来越复杂的

二、简单工厂通过构造时传入的标识来生产产品,不同产品都在同一个工厂中生产,这种判断会随着产品的增加而增加,给扩展和维护带来麻烦

三、工厂模式无法解决产品族和产品等级结构的问题

四、抽象工厂模式中,一个工厂生产多个产品,它们是一个产品族,不同的产品族的产品派生于不同的抽象产品(或产品接口)。

五、用哪种工厂模式,取决于业务需求,不要认为简单工厂是用switch case就觉得一无是处,也不要觉得抽象工厂比较高大上就到处套。要根据三种工厂模式的特质,来确定使用哪种解决问题。

简单工厂

 1         int prodNo;
 2         public SimpleFactory(int prodNo) //构造工厂时告知工厂产品标识
 3         {
 4             this.prodNo = prodNo;
 5         }
 6  
 7         public IProduct GetProduct()
 8         {
 9             switch (prodNo) //根据产品标识生产产品
10             {
11                 default:
12                     return new ProductA();
13                 case 1:
14                     return new ProductA();
15                 case 2:
16                     return new ProductB();
17             }
18  
19          }
20  
21  
22     }
23  
24     //产品A
25     class ProductA: IProduct 
26     {
27         //产品属性
28         //......
29     }
30  
31     //产品B
32     class ProductB : IProduct
33     {
34         //产品属性
35         //......
36     }
37     //产品接口
38     interface IProduct
39     {
40         //产品方法
41         //......
42     }        

那么大家看看这段简单工厂的例子,如果我现在问,这个会有什么问题,该如何回答呢?提示一下,如果说来了一个需求,增加一个产品C,该如何办?没错,简单工厂的问题就在于swich case(或者if else)。每当新增一种产品时,你都需要去维护工厂中的判断语句,造成的后果就是可能这个工厂类会非常非常长,各种判断全部挤在一起,给扩展和维护带来很多麻烦。说白了,你的产品和工厂还是没有完全解耦,绑定在一起的。所以,我们得到了第二个结论:简单工厂通过构造时传入的标识来生产产品,不同产品都在同一个工厂中生产,这种判断会随着产品的增加而增加,给扩展和维护带来麻烦。那么,如何解决这个问题呢?

你猜对了,工厂模式可以解决这个问题:

 

工厂模式

 1     interface IFactory //工厂接口
 2     {
 3         IProduct GetProduct();
 4     }
 5  
 6     //A工厂类
 7     public class FactoryA: IFactory
 8     {
 9         IProduct productA;
10         public FactoryA()
11         {
12             this.productA = new ProductA();
13         }
14  
15         public IProduct GetProduct() //A工厂生产A产品
16         {
17             return this.productA;
18         }
19     }
20  
21     //B工厂类
22     public class FactoryB : IFactory
23     {
24         IProduct productB;
25         public FactoryB()
26         {
27             this.productB = new ProductB();
28         }
29  
30         public IProduct GetProduct() //B工厂生产B产品
31         {
32             return this.productB;
33         }
34     }
35  
36     //产品接口
37     public interface IProduct
38     {
39         //产品方法
40         //......
41     }
42  
43     //产品A
44     public class ProductA : IProduct
45     {
46         //产品属性
47         //......
48     }
49  
50     //产品B
51     public class ProductB : IProduct
52     {
53         //产品属性
54         //......
55     }

仔细观察这段代码,在工厂模式中,已经将工厂类分开,不再将所有产品在同一工厂中生产,这样就解决了简单工厂中不停的switch case的问题。如果说来了一个C产品,那么我们只需要写一个C工厂和C产品,在调用时用C工厂生产C产品即可,A和B工厂和产品完全不受影响。OK,优化说完了,但是还是有问题。

 

问题在哪里呢?当业务需求是需要生产产品族的时候,工厂就不再适合了。举个栗子:我想生产三星的洗衣机和格力的洗衣机,两个都是洗衣机,但是品牌不同,这个叫产品等级结构。最近格力的产品好卖,我想去生产格力的产品,不管是洗衣机还是冰箱都可以,只要是格力的就行,这个叫做产品族。而工厂模式无法解决产品族和产品等级结构的问题。这就要用到抽象工厂模式了。

 

抽象工厂

 1         //工厂接口,即抽象工厂
 2         interface IFactory
 3         {
 4             IFridge CreateFridge();
 5             IAirCondition CreateAirCondition();
 6         }
 7  
 8  
 9         //三星的工厂,生产三星的产品族
10         public class SamsungFactory : IFactory
11         {
12   
13             public IAirCondition CreateAirCondition() 
14             {
15                 return new SamsungAirCondition(); //三星的工厂生产三星的空调
16               
17             }
18  
19             public IFridge CreateFridge()
20             {
21                 return new SamsungFridge(); //三星的工厂生产三星的冰箱
22             }
23         }
24  
25         //格力的工厂,生产格力的产品族
26  
27         public class GreeFactry : IFactory
28         {
29             public IAirCondition CreateAirCondition()
30             {
31                 return new GreeAirCondition(); //格力的工厂生产格力的空调
32             }
33  
34             public IFridge CreateFridge()
35             {
36                 return new GreeFridge(); //格力的工厂生产格力的冰箱
37             }
38         }
39  
40         //冰箱产品接口
41         public interface IFridge
42         {
43             //冰箱产品接口
44             //冰箱的action
45         }
46  
47         //空调接口
48         public interface IAirCondition
49         {
50             //空调产品接口
51             //空调的action
52         }
53  
54         //三星的冰箱
55         public class SamsungFridge: IFridge
56         {
57            //三星冰箱的action和property
58         }
59         //格力的冰箱
60         public class GreeFridge : IFridge
61         {
62              //格力冰箱的action和property
63         }
64  
65         //三星的空调
66         public class SamsungAirCondition : IAirCondition
67         {
68            //三星空调的action和property
69         }
70         //格力的空调
71         public class GreeAirCondition : IAirCondition
72         {
73             //格力空调的action和property
74         }

 

我们可以看到,三星这个工厂里面产三星空调和三星冰箱,这是一个产品族,而三星冰箱也是冰箱啊,所以它派生于冰箱这个产品。

在上面的代码中,都使用了接口来表达抽象工厂或者抽象产品,那么可以用抽象类吗?

从功能上说,完全可以,甚至可以用接口来定义行为,用抽象类来抽象属性。抽象类更加偏向于属性的抽象,而用接口更加偏向行为的规范与统一。使用接口有更好的可扩展性和可维护性,更加灵活实现松散耦合,所以编程原则中有一条是针对接口编程而不是针对类编程。

posted @ 2018-03-21 10:18  hanhuihanhui  阅读(224)  评论(0编辑  收藏  举报