《Head First 设计模式》是本不错的讲解设计模式的书,不像F4写的那么枯燥,应该算是比较容易理解的好书。书中的例子都比较浅显易懂,不过由于是外国佬写的,所以例子的习惯不是很附合中国特色,可能偶尔看起来有些别扭,还有语言习惯也不是中国风。当然��看过这本书之后,你才能深刻理解设计模式到底能为你解决哪些问题,不能为你解决哪些问题(比如不能代替你的编码)。
我将书中部分代码改成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
|
<?php
/**
* 策略模式
* 定义了算法族,分别封装起来,让它们之间可以互相替换,
* 此模式让算法的变化独立于使用算法的客户。
*/
//飞行行为接口
interface
FlyBehavior {
public
function
fly();
}
//呱呱叫行为接口
interface
QuackBehavior {
public
function
quack();
}
//翅膀飞行
class
FlyWithWings
implements
FlyBehavior {
public
function
fly() {
echo
"I'm flying!!n"
;
}
}
//不会飞
class
FlyNoWay
implements
FlyBehavior {
public
function
fly() {
echo
"I can't fly!n"
;
}
}
class
FlyRocketPowered
implements
FlyBehavior {
public
function
fly() {
echo
"I'm flying with a rocket!n"
;
}
}
class
Qquack
implements
QuackBehavior {
public
function
quack() {
echo
"Quackn"
;
}
}
class
Squeak
implements
QuackBehavior {
public
function
quack() {
echo
"Squeakn"
;
}
}
class
MuteQuack
implements
QuackBehavior {
public
function
quack() {
echo
"<< Silence >>n"
;
}
}
abstract
class
Duck {
protected
$quack_obj
;
protected
$fly_obj
;
public
abstract
function
display();
public
function
performQuack() {
$this
->quack_obj->quack();
}
public
function
performFly() {
$this
->fly_obj->fly();
}
public
function
swim() {
echo
"All ducks float, even decoys!n"
;
}
public
function
setFlyBehavior(FlyBehavior
$fb
) {
$this
->fly_obj =
$fb
;
}
public
function
setQuackBehavior(QuackBehavior
$qb
) {
$this
->quack_obj =
$qb
;
}
}
class
ModelDuck
extends
Duck {
public
function
__construct() {
$this
->fly_obj =
new
FlyNoWay();
$this
->quack_obj =
new
MuteQuack();
}
public
function
display() {
echo
"I'm a model duck!n"
;
}
}
$model
=
new
ModelDuck();
$model
->performFly();
$model
->performQuack();
//提供新的能力
$model
->setFlyBehavior(
new
FlyRocketPowered());
$model
->setQuackBehavior(
new
Squeak());
$model
->performFly();
$model
->performQuack();
?>
|
单件模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<?php
/**
* 单件模式
* 确保一个类只有一个实例,并提供一个全局访问点。
*/
class
MyClass {
private
static
$uniqueInstance
;
private
function
__construct() {
}
public
static
function
getInstance() {
if
(self::
$uniqueInstance
== null) {
self::
$uniqueInstance
=
new
MyClass();
}
return
self::
$uniqueInstance
;
}
}
$myClass
= MyClass::getInstance();
var_dump(
$myClass
);
$myClass
= MyClass::getInstance();
var_dump(
$myClass
);
?>
|
工厂方法模式
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
<?php
abstract
class
PizzaStore {
public
function
orderPizza(
$type
) {
$pizza
=
$this
->createPizza(
$type
);
$pizza
->prepare();
$pizza
->bake();
$pizza
->cut();
$pizza
->box();
return
$pizza
;
}
public
abstract
function
createPizza(
$type
);
}
class
NYPizzaStore
extends
PizzaStore {
public
function
createPizza(
$type
) {
if
(
$type
==
"cheese"
) {
return
new
NYStyleCheesePizza();
}
elseif
(
$type
==
"veggie"
) {
return
new
NYStyleVeggiePizza();
}
elseif
(
$type
==
"clam"
) {
return
new
NYStyleClamPizza();
}
elseif
(
$type
==
"papperoni"
) {
return
new
NYStylePapperoniPizza();
}
else
{
return
null;
}
}
}
class
ChicagoPizzaStore
extends
PizzaStore {
public
function
createPizza(
$type
) {
if
(
$type
==
"cheese"
) {
return
new
ChicagoStyleCheesePizza();
}
elseif
(
$type
==
"veggie"
) {
return
new
ChicagoStyleVeggiePizza();
}
elseif
(
$type
==
"clam"
) {
return
new
ChicagoStyleClamPizza();
}
elseif
(
$type
==
"papperoni"
) {
return
new
ChicagoStylePapperoniPizza();
}
else
{
return
null;
}
}
}
abstract
class
Pizza {
public
$name
;
public
$dough
;
public
$sauce
;
public
$toppings
=
array
();
public
function
prepare() {
echo
"Preparing "
.
$this
->name .
"n"
;
echo
"Yossing dough...n"
;
echo
"Adding sauce...n"
;
echo
"Adding toppings: n"
;
for
(
$i
= 0;
$i
<
count
(
$this
->toppings);
$i
++) {
echo
" "
.
$this
->toppings[
$i
] .
"n"
;
}
}
public
function
bake() {
echo
"Bake for 25 minutes at 350n"
;
}
public
function
cut() {
echo
"Cutting the pizza into diagonal slicesn"
;
}
public
function
box() {
echo
"Place pizza in official PizzaStore boxn"
;
}
public
function
getName() {
return
$this
->name;
}
}
class
NYStyleCheesePizza
extends
Pizza {
public
function
__construct() {
$this
->name =
"NY Style Sauce and cheese Pizza"
;
$this
->dough =
"Thin Crust Dough"
;
$this
->sauce =
"Marinara Sauce"
;
$this
->toppings[] =
"Grated Reggiano Cheese"
;
}
}
class
NYStyleVeggiePizza
extends
Pizza {
public
function
__construct() {
$this
->name =
"NY Style Sauce and veggie Pizza"
;
$this
->dough =
"Thin Crust Dough"
;
$this
->sauce =
"Marinara Sauce"
;
$this
->toppings[] =
"Grated Reggiano veggie"
;
}
}
class
NYStyleClamPizza
extends
Pizza {
public
function
__construct() {
$this
->name =
"NY Style Sauce and clam Pizza"
;
$this
->dough =
"Thin Crust Dough"
;
$this
->sauce =
"Marinara Sauce"
;
$this
->toppings[] =
"Grated Reggiano clam"
;
}
}
class
NYStylePapperoniPizza
extends
Pizza {
public
function
__construct() {
$this
->name =
"NY Style Sauce and papperoni Pizza"
;
$this
->dough =
"Thin Crust Dough"
;
$this
->sauce =
"Marinara Sauce"
;
$this
->toppings[] =
"Grated Reggiano papperoni"
;
}
}
class
ChicagoStyleCheesePizza
extends
Pizza {
public
function
__construct() {
$this
->name =
"Chicago Style Deep Dish Cheese Pizza"
;
$this
->dough =
"Extra Thick Crust Dough"
;
$this
->sauce =
"Plum Tomato Sauce"
;
$this
->toppings[] =
"Shredded Mozzarella Cheese"
;
}
public
function
cut() {
echo
"Cutting the pizza into square slicesn"
;
}
}
$myStore
=
new
NYPizzaStore();
$chicagoStore
=
new
ChicagoPizzaStore();
$pizza
=
$myStore
->orderPizza(
"cheese"
);
echo
"Ethan ordered a "
.
$pizza
->getName() .
"n"
;
$pizza
=
$chicagoStore
->orderPizza(
"cheese"
);
echo
"Ethan ordered a "
.
$pizza
->getName() .
"n"
;
?>
|
工厂模式
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
<?php
abstract
class
PizzaStore {
public
function
orderPizza(
$type
) {
$pizza
=
$this
->createPizza(
$type
);
$pizza
->prepare();
$pizza
->bake();
$pizza
->cut();
$pizza
->box();
return
$pizza
;
}
public
abstract
function
createPizza(
$type
);
}
class
NYPizzaStore
extends
PizzaStore {
public
function
createPizza(
$type
) {
$pizza
= null;
$ingredientFactory
=
new
NYPizzaIngredientFactory();
if
(
$type
==
"cheese"
) {
$pizza
=
new
CheesePizza(
$ingredientFactory
);
$pizza
->setName(
'New York Style Cheese Pizza'
);
}
elseif
(
$type
==
"veggie"
) {
$pizza
=
new
VeggiePizza(
$ingredientFactory
);
$pizza
->setName(
'New York Style Veggie Pizza'
);
}
elseif
(
$type
==
"clam"
) {
$pizza
=
new
ClamPizza(
$ingredientFactory
);
$pizza
->setName(
'New York Style Clam Pizza'
);
}
elseif
(
$type
==
"papperoni"
) {
$pizza
=
new
PapperoniPizza(
$ingredientFactory
);
$pizza
->setName(
'New York Style Papperoni Pizza'
);
}
return
$pizza
;
}
}
class
ChicagoPizzaStore
extends
PizzaStore {
public
function
createPizza(
$type
) {
if
(
$type
==
"cheese"
) {
return
new
ChicagoStyleCheesePizza();
}
elseif
(
$type
==
"veggie"
) {
return
new
ChicagoStyleVeggiePizza();
}
elseif
(
$type
==
"clam"
) {
return
new
ChicagoStyleClamPizza();
}
elseif
(
$type
==
"papperoni"
) {
return
new
ChicagoStylePapperoniPizza();
}
else
{
return
null;
}
}
}
interface
PizzaIngredientFactory {
public
function
createDough();
public
function
createSauce();
public
function
createCheese();
public
function
createVeggies();
public
function
createPepperoni();
public
function
createClam();
}
class
NYPizzaIngredientFactory
implements
PizzaIngredientFactory {
public
function
createDough() {
return
new
ThinCrustDough();
}
public
function
createSauce() {
return
new
MarinaraSauce();
}
public
function
createCheese() {
return
new
ReggianoCheese();
}
public
function
createVeggies() {
$veggies
=
array
(
new
Garlic(),
new
Onion(),
new
Mushroom(),
new
RedPepper(),
);
return
$veggies
;
}
public
function
createPepperoni() {
return
new
SlicedPepperoni();
}
public
function
createClam() {
return
new
FreshClams();
}
}
class
ChicagoPizzaIngredientFactory
implements
PizzaIngredientFactory {
public
function
createDough() {
return
new
ThickCrustDough();
}
public
function
createSauce() {
return
new
PlumTomatoSauce();
}
public
function
createCheese() {
return
new
Mozzarella();
}
public
function
createVeggies() {
$veggies
=
array
(
new
BlackOlives(),
new
Spinach(),
new
EggPlant(),
);
return
$veggies
;
}
public
function
createPepperoni() {
return
new
SlicedPepperoni();
}
public
function
createClam() {
return
new
FrozenClams();
}
}
abstract
class
Pizza {
public
$name
;
public
$dough
;
public
$sauce
;
public
$veggies
=
array
();
public
$cheese
;
public
$pepperoni
;
public
$clam
;
public
abstract
function
prepare();
public
function
bake() {
echo
"Bake for 25 minutes at 350n"
;
}
public
function
cut() {
echo
"Cutting the pizza into diagonal slicesn"
;
}
public
function
box() {
echo
"Place pizza in official PizzaStore boxn"
;
}
public
function
getName() {
return
$this
->name;
}
public
function
setName(
$name
) {
$this
->name =
$name
;
}
public
function
__toString() {
}
}
class
CheesePizza
extends
Pizza {
public
$ingredientFactory
;
public
function
__construct(PizzaIngredientFactory
$ingredientFactory
) {
$this
->ingredientFactory =
$ingredientFactory
;
}
public
function
prepare() {
echo
"Preparing "
.
$this
->name .
"n"
;
$this
->dough =
$this
->ingredientFactory->createDough();
$this
->sauce =
$this
->ingredientFactory->createSauce();
$this
->cheese =
$this
->ingredientFactory->createCheese();
}
}
class
ClamPizza
extends
Pizza {
public
$ingredientFactory
;
public
function
__construct(PizzaIngredientFactory
$ingredientFactory
) {
$this
->ingredientFactory =
$ingredientFactory
;
}
public
function
prepare() {
echo
"Preparing "
.
$this
->name .
"n"
;
$this
->dough =
$this
->ingredientFactory->createDough();
$this
->sauce =
$this
->ingredientFactory->createSauce();
$this
->cheese =
$this
->ingredientFactory->createCheese();
$clam
=
$this
->ingredientFactory->createClam();
}
}
$nyPizzaStore
=
new
NYPizzaStore();
$nyPizzaStore
->orderPizza(
'cheese'
);
?>
|
观察者模式
<?php
/**
* 观察者模式
* 定义了对象之间的一对多依赖,当一个对象改变状态时,
* 它的所有依赖者都会收到通知并自动更新。
*/
interface
Subject {
public
function
registerObserver(Observer
$o
);
public
function
removeObserver(Observer
$o
);
public
function
notifyObservers();
}
interface
Observer {
public
function
update(
$temperature
,
$humidity
,
$pressure
);
}
interface
DisplayElement {
public
function
display();
}
class
WeatherData
implements
Subject {
private
$observers
=
array
();
private
$temperature
;
private
$humidity
;
private
$pressure
;
public
function
__construct() {
$this
->observers =
array
();
}
public
function
registerObserver(Observer
$o
) {
$this
->observers[] =
$o
;
}
public
function
removeObserver(Observer
$o
) {
if
((
$key
=
array_search
(
$o
,
$this
->observers)) !== false) {
unset(
$this
->observers[
$key
]);
}
}
public
function
notifyObservers() {
foreach
(
$this
->observers
as
$observer
) {
$observer
->update(
$this
->temperature,
$this
->humidity,
$this
->pressure);
}
}
public
function
measurementsChanged() {
$this
->notifyObservers();
}
public
function
setMeasurements(
$temperature
,
$humidity
,
$pressure
) {
$this
->temperature =
$temperature
;
$this
->humidity =
$humidity
;
$this
->pressure =
$pressure
;
$this
->measurementsChanged();
}
}
class
CurrentConditionsDisplay
implements
Observer, DisplayElement {
private
$temperature
;
private
$humidity
;
private
$weatherData
;
public
function
__construct(Subject
$weatherData
) {
$this
->weatherData =
$weatherData
;
$weatherData
->registerObserver(
$this
);
}
public
function
update(
$temperature
,
$humidity
,
$pressure
) {
$this
->temperature =
$temperature
;
$this
->humidity =
$humidity
;
$this
->display();
}
public
function
display() {
echo
"温度:"
.
$this
->temperature .
"; 湿度:"
.
$this
->humidity .
"%n"
;
}
}
class
StatistionsDisplay
implements
Observer, DisplayElement {
private
$temperature
;
private
$humidity
;
private
$pressure
;
private
$weatherData
;
public
function
__construct(Subject
$weatherData
) {
$this
->weatherData =
$weatherData
;
$weatherData
->registerObserver(
$this
);
}
public
function
update(
$temperature
,
$humidity
,
$pressure
) {
$this
->temperature =
$temperature
;
$this
->humidity =
$humidity
;
$this
->pressure =
$pressure
;
$this
->display();
}
public
function
display() {
echo
"温度:"
.
$this
->temperature .
"; 湿度:"
.
$this
->humidity .
"%; 气压:"
.
$this
->pressure .
"n"
;
}
}
$weatherData
=
new
WeatherData();
$currentDisplay
=
new
CurrentConditionsDisplay(
$weatherData
);
$statistionDisplay
=
new
StatistionsDisplay(
$weatherData
);
$weatherData
->setMeasurements(10, 20, 30);
$weatherData
->removeObserver(
$currentDisplay
);
$weatherData
->setMeasurements(30, 40, 50);
?>
|
命令模式
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
|
<?php
class
Light {
public
function
__construct() {
}
public
function
on() {
echo
"Light Onn"
;
}
public
function
off() {
echo
"Light Offn"
;
}
}
interface
Command {
public
function
execute();
}
class
LightOnCommand
implements
Command {
public
$light
;
public
function
__construct(Light
$light
) {
$this
->light =
$light
;
}
public
function
execute() {
$this
->light->on();
}
}
class
SimpleRemoteControl {
public
$slot
;
public
function
__construct() {
}
public
function
setCommand(Command
$command
) {
$this
->slot =
$command
;
}
public
function
buttonWasPressed() {
$this
->slot->execute();
}
}
class
RemoteControlTest {
public
static
function
main() {
$remote
=
new
SimpleRemoteControl();
$light
=
new
Light();
$lightOn
=
new
LightOnCommand(
$light
);
$remote
->setCommand(
$lightOn
);
$remote
->buttonWasPressed();
}
}
RemoteControlTest::main();
?>
|
装饰者模式
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
|
<?php
/**
* 装饰着模式
* 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
*/
abstract
class
Beverage {
public
$description
=
"Unknown Beverage"
;
public
function
getDescription() {
return
$this
->description;
}
public
abstract
function
cost();
}
abstract
class
CondimentDecorator
extends
Beverage {
//JAVA代码里这里是个抽象类,PHP不允许这么做
public
function
getDescription() {
return
$this
->description;
}
}
class
Espresso
extends
Beverage {
public
function
__construct() {
$this
->description =
"Espresso"
;
}
public
function
cost() {
return
1.99;
}
}
class
HouseBlend
extends
Beverage {
public
function
__construct() {
$this
->description =
"HouseBlend"
;
}
public
function
cost() {
return
.89;
}
}
class
DarkRoast
extends
Beverage {
public
function
__construct() {
$this
->description =
"DarkRoast"
;
}
public
function
cost() {
return
.99;
}
}
class
Mocha
extends
CondimentDecorator {
public
$beverage
;
public
function
__construct(Beverage
$beverage
) {
$this
->beverage =
$beverage
;
}
public
function
getDescription() {
return
$this
->beverage->getDescription() .
", Mocha"
;
}
public
function
cost() {
return
.20 +
$this
->beverage->cost();
}
}
class
Whip
extends
CondimentDecorator {
public
$beverage
;
public
function
__construct(Beverage
$beverage
) {
$this
->beverage =
$beverage
;
}
public
function
getDescription() {
return
$this
->beverage->getDescription() .
", Whip"
;
}
public
function
cost() {
return
.10 +
$this
->beverage->cost();
}
}
class
Soy
extends
CondimentDecorator {
public
$beverage
;
public
function
__construct(Beverage
$beverage
) {
$this
->beverage =
$beverage
;
}
public
function
getDescription() {
return
$this
->beverage->getDescription() .
", Soy"
;
}
public
function
cost() {
return
.15 +
$this
->beverage->cost();
}
}
$beverage
=
new
Espresso();
echo
$beverage
->getDescription() .
"n"
;
$beverage2
=
new
DarkRoast();
$beverage2
=
new
Mocha(
$beverage2
);
$beverage2
=
new
Mocha(
$beverage2
);
$beverage2
=
new
Whip(
$beverage2
);
echo
$beverage2
->getDescription() .
" $"
.
$beverage2
->cost() .
"n"
;
$beverage3
=
new
HouseBlend();
$beverage3
=
new
Soy(
$beverage3
);
$beverage3
=
new
Mocha(
$beverage3
);
$beverage3
=
new
Whip(
$beverage3
);
echo
$beverage3
->getDescription() .
" $"
.
$beverage3
->cost() .
"n"
;
?>
|
状态模式
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
|
<?php
class
GumballMachine {
const
SOLD_OUT = 0;
const
NO_QUARTER = 1;
const
HAS_QUARTER = 2;
const
SOLD = 3;
public
$state
= self::SOLD_OUT;
public
$count
= 0;
public
function
__construct(
$count
) {
$this
->
count
=
$count
;
if
(
$count
> 0) {
$this
->state = self::NO_QUARTER;
}
}
public
function
insertQuarter() {
if
(
$this
->state == self::HAS_QUARTER) {
echo
"You can't insert another quarter!n"
;
}
else
if
(
$this
->state == self::NO_QUARTER) {
$this
->state = self::HAS_QUARTER;
echo
"You inserted a quarter!n"
;
}
else
if
(
$this
->state == self::SOLD_OUT) {
echo
"You can't insert a quarter, the machine is sold out!n"
;
}
else
if
(
$this
->state == self::SOLD) {
echo
"Please wait, we're already giving you a gumball!n"
;
}
}
}
$obj
=
new
GumballMachine(0);
print_r(
$obj
)
?>
|