《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 )
?> |