0%

工厂模式之抽象工厂模式-创建型

抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。多个产品等级结构构成了一个产品族。

VS 工厂方法

工厂方法模式对应:零件产品接口、车轮产品、发动机产品、零件工厂接口、车轮产品工厂、发动机产品工厂。车轮与发动机属于同一个产品等级,都属于零件这个产品等级。

抽象工厂方法对应:发动机产品接口、轿车发动机产品、巴士发动机产品、车轮产品接口、轿车车轮产品、巴士车轮产品、机动车工厂接口、轿车工厂、巴士工厂。

产品等级结构:车轮是一个产品等级(轿车发动机产品、巴士发动机产品),发动机也是一个产品等级。

产品族:是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。如车轮与发动机由同一个工厂生产,构成了一个产品族。

优点

当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。

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

如:我们现在要增加SUV产品族。我们可以增加SUV发动机、SUV车轮、再增加一个SUV工厂即可。

缺点

开闭原则的倾斜性(增加新的产品等级结构麻烦)。

如:我们现在要增加一个变速箱产品,我们需要:

增加变速箱产品接口、轿车变速箱产品、巴士变速箱产品

修改所有工厂实现和工厂接口。增加创建变速箱的方法。因为工厂是一个产品族,需要包含了所有产品。

适用

系统中有多于一个的产品族,而每次只使用其中某一产品族。

属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。

系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

扩展

增加产品族:对于增加新的产品族,工厂方法模式很好的支持了“开闭原则”,对于新增加的产品族,只需要对应增加一个新的具体工厂,补充已有的产品。

增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,不能很好地支持“开闭原则”。

当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。

PHP 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?php
/**
* Interface Engine
*/
interface Engine
{
public function produce();
}

/**
* Class CarEngine
*/
class CarEngine implements Engine
{
public function produce()
{
echo '生产Car发动机';
echo PHP_EOL;
}
}

/**
* Class BusEngine
*/
class BusEngine implements Engine
{
public function produce()
{
echo '生产Bus发动机';
echo PHP_EOL;
}
}

/**
* Interface Wheel
*/
interface Wheel
{
public function produce();
}

/**
* Class CarWheel
*/
class CarWheel implements Wheel
{
public function produce()
{
echo '生产Car车轮';
echo PHP_EOL;
}
}

/**
* Class BusWheel
*/
class BusWheel implements Wheel
{
public function produce()
{
echo '生产Bus车轮';
echo PHP_EOL;
}
}

/**
* Interface Factory
*/
interface Factory
{
public function engine();
public function wheel();
}

/**
* Class CarFactory
*/
class CarFactory implements Factory
{
public function engine()
{
return new CarEngine();
}

public function wheel()
{
return new CarWheel();
}
}

/**
* Class BusFactory
*/
class BusFactory implements Factory
{
public function engine()
{
return new BusEngine();
}

public function wheel()
{
return new BusWheel();
}
}

$carFactory = new CarFactory();
$carEngine = $carFactory->engine();
$carWheel = $carFactory->wheel();
var_dump($carEngine);
var_dump($carWheel);
$carWheel->produce();

$busFactory = new BusFactory();
$busEngine = $busFactory->engine();
$busWheel = $busFactory->wheel();
var_dump($busEngine);
var_dump($busWheel);
$busEngine->produce();