The factory pattern
通常一个对象或者类之中也包含了其他的对象,当需要创建这些成员对象的时候。如果能直接实例化他们会是非常不错的选择。使用new这个关键字和相应的构造函数。这之中的问题是这样就增加了两个类的耦合度。在这章中。我们关注这个设计模式 可以减弱这个问题的后果。同时使用一个方法决定哪个类需要实例化来代替。我们讨论简单的 工厂模式。这种方式使用分离的类(通常是一个单件)以便创建一个实例。同时更复杂的工厂模式,使用子类决定具体要实例化的类.
The simple factory
简单工厂模式是最好用一个例子来实践,我们设置一个背景:你需要一些自行车的商店。每一个商店提供一些样子的自行车出售。这可以用下面的类表示。

BicycleShop class
1 /* BicycleShop class*/
2
3 var BicycleShop=function(){}
4
5 BicycleShop.prototype={
6
7 sellBicycle:function(model){
8
9 var bicycle;
10
11 switch(model){
12
13 case 'The Speedster':
14
15 bicycle=new Speedster();
16
17 break;
18
19 case 'The LowRider':
20
21 bicycle=new LowRider()
22
23 break;
24
25 case 'The Comfort':
26
27 default:
28
29 bicycle=new Comfort()
30
31 }
32
33 Interface.ensureImplements(bicycle,BicycleShop);
34
35 bicycle.assemble();
36
37 bicycle.wash();
38
39 return bicycle;
40
41 }
42
43 }
44
45
你检查那一个bicycle的模型是被请求的 然后用swith 条件为这个对象创建一个实例。你能在这些类型中选择因为他们都在Bicycle这个类的接口中。

the interface of the Bicycle
1 /*the interface of the Bicycle*/
2
3 var Bicycle=new Interface('Bicycle',['assemble','wash','ride','repair']);
4
5 /*the Speedster class*/
6
7 var Speedster=function(){//implements the Bicycle
8
9 //
..
10
11 }
12
13 Speedster.prototype={
14
15 assemble:function(){
16
17 //
18
19 },
20
21 wash:function(){
22
23 //
24
25 },
26
27 ride : function(){
28
29 //..
30
31 },
32
33 repair:function(){
34
35 //..
36
37 }
38
39 };
40
41
为了sell一辆一定模式的自行车,调用sellBicyle这个方法。
1 var a=new BicycleShop();
2
3 var yourNewBike=a.sellBicycle('The Speedster');
4
直到你想做一些改变之前代码它都能自如的工作。如果你想添加一个新的类型的自行车到你的商店中呢,这样就要求你改变BicycleShop中的方法。即使你没有实际更改BicycleShop中的代码,你依然创建了一个bike的实例,先调用组装的方法 ,然后清洗他,最后把它给你的用户。一个更好的解决方式是终止创建一个新的实例的部分方法而选择一个简单的工厂对象。

BicycleFactorty namespace
1 /*BicycleFactorty namespace*/
2
3 var BicycleFactory={
4
5 createBicycle:function(model){
6
7 var bicycle;
8
9 switch(model){
10
11 case 'The Speedster':
12
13 bicycle=new Speedster();
14
15 break;
16
17 case 'The Lowrider':
18
19 bicycle=new Lowrider();
20
21 break;
22
23 case 'The Comfort Cruiser':
24
25 default:
26
27 bicycle=new Cruiser();
28
29 }
30
31 Interface.ensureImplements(bicycle,Bicycle);
32
33 return bicycle;
34
35 }
36
37 }
38
39
BicycleFactory是一个作为一个包含createBicycle这个方法的命名空间单一对象。这个方法返回一个和回应Bicycle接口对象。这样也能想以前那样调用组装和清洗的方法了。

BicycleShop improved
1 //BicycleShop improved
2
3 var BicycleShop=function(){
4
5
6
7 }
8
9 BicycleShop.prototype={
10
11 sellBicycle:function(model){
12
13 var bicylce=BicycleFactory.createBicycle(model);
14
15 bicylce.assemble();
16
17 bicylce.wash();
18
19 return bicylce;
20
21 }
22
23 };
24
25
这样就能创建任意数量的BicycleFactory对象的实例。所有的关于模型的信息集中在一个地方。这个就意味着更容易添加自行车的模型量。

BicycleFactorty namespace
1 /*BicycleFactorty namespace*/
2
3 var BicycleFactory={
4
5 createBicycle:function(model){
6
7 var bicycle;
8
9 switch(model){
10
11 case 'The Speedster':
12
13 bicycle=new Speedster();
14
15 break;
16
17 case 'The Lowrider':
18
19 bicycle=new Lowrider();
20
21 break;
22
23 case 'The Flatrider' :
24
25 bicycle=new Flatrider();
26
27 break;
28
29 case 'The Comfort Cruiser':
30
31 default:
32
33 bicycle=new Cruiser();
34
35 }
36
37 Interface.ensureImplements(bicycle,Bicycle);
38
39 return bicycle;
40
41 }
42
43 }
44
45
BicycleFactory 是一个简单工厂模式很好的例子,他创建一个成员对象然后将他转移给外部对象。这个对象能是一个简单的命名空间,就像在这个例子中一样。或者是一个类的实例对象。当创建对象的方法不改变的时候使用单一对象或者静态类创建这些成员对象会更有意义。举个例子。你必须提供一些不同的bicycle类型。在类中创建一个对象比在子类中创建更有意义。