《Head First 设计模式》是本不错的讲解设计模式的书,不像F4写的那么枯燥,应该算是比较容易理解的好书。书中的例子都比较浅显易懂,不过由于是外国佬写的,所以例子的习惯不是很附合中国特色,可能偶尔看起来有些别扭,还有语言习惯也不是中国风。当然��看过这本书之后,你才能深刻理解设计模式到底能为你解决哪些问题,不能为你解决哪些问题(比如不能代替你的编码)。
我将书中部分代码改成PHP,看下代码再配合概念应该是比较容易理解了。
策略模式
04 |
* 定义了算法族,分别封装起来,让它们之间可以互相替换, |
05 |
* 此模式让算法的变化独立于使用算法的客户。 |
08 |
interface FlyBehavior { |
09 |
public function fly(); |
12 |
interface QuackBehavior { |
13 |
public function quack(); |
16 |
class FlyWithWings implements FlyBehavior { |
17 |
public function fly() { |
18 |
echo "I'm flying!!\n" ; |
22 |
class FlyNoWay implements FlyBehavior { |
23 |
public function fly() { |
24 |
echo "I can't fly!\n" ; |
27 |
class FlyRocketPowered implements FlyBehavior { |
28 |
public function fly() { |
29 |
echo "I'm flying with a rocket!\n" ; |
32 |
class Qquack implements QuackBehavior { |
33 |
public function quack() { |
37 |
class Squeak implements QuackBehavior { |
38 |
public function quack() { |
42 |
class MuteQuack implements QuackBehavior { |
43 |
public function quack() { |
44 |
echo "<< Silence >>\n" ; |
50 |
public abstract function display(); |
52 |
public function performQuack() { |
53 |
$this ->quack_obj->quack(); |
55 |
public function performFly() { |
56 |
$this ->fly_obj->fly(); |
58 |
public function swim() { |
59 |
echo "All ducks float, even decoys!\n" ; |
61 |
public function setFlyBehavior(FlyBehavior $fb ) { |
64 |
public function setQuackBehavior(QuackBehavior $qb ) { |
65 |
$this ->quack_obj = $qb ; |
69 |
class ModelDuck extends Duck { |
70 |
public function __construct() { |
71 |
$this ->fly_obj = new FlyNoWay(); |
72 |
$this ->quack_obj = new MuteQuack(); |
74 |
public function display() { |
75 |
echo "I'm a model duck!\n" ; |
79 |
$model = new ModelDuck(); |
81 |
$model ->performQuack(); |
83 |
$model ->setFlyBehavior( new FlyRocketPowered()); |
84 |
$model ->setQuackBehavior( new Squeak()); |
86 |
$model ->performQuack(); |
单件模式
04 |
* 确保一个类只有一个实例,并提供一个全局访问点。 |
07 |
private static $uniqueInstance ; |
08 |
private function __construct() { |
11 |
public static function getInstance() { |
12 |
if (self:: $uniqueInstance == null) { |
13 |
self:: $uniqueInstance = new MyClass(); |
15 |
return self:: $uniqueInstance ; |
18 |
$myClass = MyClass::getInstance(); |
20 |
$myClass = MyClass::getInstance(); |
工厂方法模式
002 |
abstract class PizzaStore { |
003 |
public function orderPizza( $type ) { |
004 |
$pizza = $this ->createPizza( $type ); |
013 |
public abstract function createPizza( $type ); |
015 |
class NYPizzaStore extends PizzaStore { |
016 |
public function createPizza( $type ) { |
017 |
if ( $type == "cheese" ) { |
018 |
return new NYStyleCheesePizza(); |
019 |
} elseif ( $type == "veggie" ) { |
020 |
return new NYStyleVeggiePizza(); |
021 |
} elseif ( $type == "clam" ) { |
022 |
return new NYStyleClamPizza(); |
023 |
} elseif ( $type == "papperoni" ) { |
024 |
return new NYStylePapperoniPizza(); |
031 |
class ChicagoPizzaStore extends PizzaStore { |
032 |
public function createPizza( $type ) { |
033 |
if ( $type == "cheese" ) { |
034 |
return new ChicagoStyleCheesePizza(); |
035 |
} elseif ( $type == "veggie" ) { |
036 |
return new ChicagoStyleVeggiePizza(); |
037 |
} elseif ( $type == "clam" ) { |
038 |
return new ChicagoStyleClamPizza(); |
039 |
} elseif ( $type == "papperoni" ) { |
040 |
return new ChicagoStylePapperoniPizza(); |
046 |
abstract class Pizza { |
050 |
public $toppings = array (); |
052 |
public function prepare() { |
053 |
echo "Preparing " . $this ->name . "\n" ; |
054 |
echo "Yossing dough...\n" ; |
055 |
echo "Adding sauce...\n" ; |
056 |
echo "Adding toppings: \n" ; |
057 |
for ( $i = 0; $i < count ( $this ->toppings); $i ++) { |
058 |
echo " " . $this ->toppings[ $i ] . "\n" ; |
062 |
public function bake() { |
063 |
echo "Bake for 25 minutes at 350\n" ; |
066 |
public function cut() { |
067 |
echo "Cutting the pizza into diagonal slices\n" ; |
070 |
public function box() { |
071 |
echo "Place pizza in official PizzaStore box\n" ; |
074 |
public function getName() { |
079 |
class NYStyleCheesePizza extends Pizza { |
080 |
public function __construct() { |
081 |
$this ->name = "NY Style Sauce and cheese Pizza" ; |
082 |
$this ->dough = "Thin Crust Dough" ; |
083 |
$this ->sauce = "Marinara Sauce" ; |
085 |
$this ->toppings[] = "Grated Reggiano Cheese" ; |
089 |
class NYStyleVeggiePizza extends Pizza { |
090 |
public function __construct() { |
091 |
$this ->name = "NY Style Sauce and veggie Pizza" ; |
092 |
$this ->dough = "Thin Crust Dough" ; |
093 |
$this ->sauce = "Marinara Sauce" ; |
095 |
$this ->toppings[] = "Grated Reggiano veggie" ; |
098 |
class NYStyleClamPizza extends Pizza { |
099 |
public function __construct() { |
100 |
$this ->name = "NY Style Sauce and clam Pizza" ; |
101 |
$this ->dough = "Thin Crust Dough" ; |
102 |
$this ->sauce = "Marinara Sauce" ; |
104 |
$this ->toppings[] = "Grated Reggiano clam" ; |
107 |
class NYStylePapperoniPizza extends Pizza { |
108 |
public function __construct() { |
109 |
$this ->name = "NY Style Sauce and papperoni Pizza" ; |
110 |
$this ->dough = "Thin Crust Dough" ; |
111 |
$this ->sauce = "Marinara Sauce" ; |
113 |
$this ->toppings[] = "Grated Reggiano papperoni" ; |
117 |
class ChicagoStyleCheesePizza extends Pizza { |
118 |
public function __construct() { |
119 |
$this ->name = "Chicago Style Deep Dish Cheese Pizza" ; |
120 |
$this ->dough = "Extra Thick Crust Dough" ; |
121 |
$this ->sauce = "Plum Tomato Sauce" ; |
123 |
$this ->toppings[] = "Shredded Mozzarella Cheese" ; |
126 |
public function cut() { |
127 |
echo "Cutting the pizza into square slices\n" ; |
131 |
$myStore = new NYPizzaStore(); |
132 |
$chicagoStore = new ChicagoPizzaStore(); |
133 |
$pizza = $myStore ->orderPizza( "cheese" ); |
134 |
echo "Ethan ordered a " . $pizza ->getName() . "\n" ; |
136 |
$pizza = $chicagoStore ->orderPizza( "cheese" ); |
137 |
echo "Ethan ordered a " . $pizza ->getName() . "\n" ; |
工厂模式
002 |
abstract class PizzaStore { |
003 |
public function orderPizza( $type ) { |
004 |
$pizza = $this ->createPizza( $type ); |
013 |
public abstract function createPizza( $type ); |
015 |
class NYPizzaStore extends PizzaStore { |
016 |
public function createPizza( $type ) { |
018 |
$ingredientFactory = new NYPizzaIngredientFactory(); |
019 |
if ( $type == "cheese" ) { |
020 |
$pizza = new CheesePizza( $ingredientFactory ); |
021 |
$pizza ->setName( 'New York Style Cheese Pizza' ); |
022 |
} elseif ( $type == "veggie" ) { |
023 |
$pizza = new VeggiePizza( $ingredientFactory ); |
024 |
$pizza ->setName( 'New York Style Veggie Pizza' ); |
025 |
} elseif ( $type == "clam" ) { |
026 |
$pizza = new ClamPizza( $ingredientFactory ); |
027 |
$pizza ->setName( 'New York Style Clam Pizza' ); |
028 |
} elseif ( $type == "papperoni" ) { |
029 |
$pizza = new PapperoniPizza( $ingredientFactory ); |
030 |
$pizza ->setName( 'New York Style Papperoni Pizza' ); |
035 |
class ChicagoPizzaStore extends PizzaStore { |
036 |
public function createPizza( $type ) { |
037 |
if ( $type == "cheese" ) { |
038 |
return new ChicagoStyleCheesePizza(); |
039 |
} elseif ( $type == "veggie" ) { |
040 |
return new ChicagoStyleVeggiePizza(); |
041 |
} elseif ( $type == "clam" ) { |
042 |
return new ChicagoStyleClamPizza(); |
043 |
} elseif ( $type == "papperoni" ) { |
044 |
return new ChicagoStylePapperoniPizza(); |
050 |
interface PizzaIngredientFactory { |
051 |
public function createDough(); |
052 |
public function createSauce(); |
053 |
public function createCheese(); |
054 |
public function createVeggies(); |
055 |
public function createPepperoni(); |
056 |
public function createClam(); |
058 |
class NYPizzaIngredientFactory implements PizzaIngredientFactory { |
059 |
public function createDough() { |
060 |
return new ThinCrustDough(); |
062 |
public function createSauce() { |
063 |
return new MarinaraSauce(); |
065 |
public function createCheese() { |
066 |
return new ReggianoCheese(); |
068 |
public function createVeggies() { |
077 |
public function createPepperoni() { |
078 |
return new SlicedPepperoni(); |
080 |
public function createClam() { |
081 |
return new FreshClams(); |
084 |
class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory { |
085 |
public function createDough() { |
086 |
return new ThickCrustDough(); |
088 |
public function createSauce() { |
089 |
return new PlumTomatoSauce(); |
091 |
public function createCheese() { |
092 |
return new Mozzarella(); |
094 |
public function createVeggies() { |
102 |
public function createPepperoni() { |
103 |
return new SlicedPepperoni(); |
105 |
public function createClam() { |
106 |
return new FrozenClams(); |
109 |
abstract class Pizza { |
113 |
public $veggies = array (); |
118 |
public abstract function prepare(); |
120 |
public function bake() { |
121 |
echo "Bake for 25 minutes at 350\n" ; |
124 |
public function cut() { |
125 |
echo "Cutting the pizza into diagonal slices\n" ; |
128 |
public function box() { |
129 |
echo "Place pizza in official PizzaStore box\n" ; |
132 |
public function getName() { |
136 |
public function setName( $name ) { |
140 |
public function __toString() { |
145 |
class CheesePizza extends Pizza { |
146 |
public $ingredientFactory ; |
148 |
public function __construct(PizzaIngredientFactory $ingredientFactory ) { |
149 |
$this ->ingredientFactory = $ingredientFactory ; |
152 |
public function prepare() { |
153 |
echo "Preparing " . $this ->name . "\n" ; |
154 |
$this ->dough = $this ->ingredientFactory->createDough(); |
155 |
$this ->sauce = $this ->ingredientFactory->createSauce(); |
156 |
$this ->cheese = $this ->ingredientFactory->createCheese(); |
160 |
class ClamPizza extends Pizza { |
161 |
public $ingredientFactory ; |
163 |
public function __construct(PizzaIngredientFactory $ingredientFactory ) { |
164 |
$this ->ingredientFactory = $ingredientFactory ; |
167 |
public function prepare() { |
168 |
echo "Preparing " . $this ->name . "\n" ; |
169 |
$this ->dough = $this ->ingredientFactory->createDough(); |
170 |
$this ->sauce = $this ->ingredientFactory->createSauce(); |
171 |
$this ->cheese = $this ->ingredientFactory->createCheese(); |
172 |
$clam = $this ->ingredientFactory->createClam(); |
176 |
$nyPizzaStore = new NYPizzaStore(); |
177 |
$nyPizzaStore ->orderPizza( 'cheese' ); |
观察者模式
04 |
* 定义了对象之间的一对多依赖,当一个对象改变状态时, |
08 |
public function registerObserver(Observer $o ); |
09 |
public function removeObserver(Observer $o ); |
10 |
public function notifyObservers(); |
13 |
public function update( $temperature , $humidity , $pressure ); |
15 |
interface DisplayElement { |
16 |
public function display(); |
18 |
class WeatherData implements Subject { |
19 |
private $observers = array (); |
23 |
public function __construct() { |
24 |
$this ->observers = array (); |
26 |
public function registerObserver(Observer $o ) { |
27 |
$this ->observers[] = $o ; |
29 |
public function removeObserver(Observer $o ) { |
30 |
if (( $key = array_search ( $o , $this ->observers)) !== false) { |
31 |
unset( $this ->observers[ $key ]); |
34 |
public function notifyObservers() { |
35 |
foreach ( $this ->observers as $observer ) { |
36 |
$observer ->update( $this ->temperature, $this ->humidity, $this ->pressure); |
39 |
public function measurementsChanged() { |
40 |
$this ->notifyObservers(); |
42 |
public function setMeasurements( $temperature , $humidity , $pressure ) { |
43 |
$this ->temperature = $temperature ; |
44 |
$this ->humidity = $humidity ; |
45 |
$this ->pressure = $pressure ; |
46 |
$this ->measurementsChanged(); |
49 |
class CurrentConditionsDisplay implements Observer, DisplayElement { |
53 |
public function __construct(Subject $weatherData ) { |
54 |
$this ->weatherData = $weatherData ; |
55 |
$weatherData ->registerObserver( $this ); |
57 |
public function update( $temperature , $humidity , $pressure ) { |
58 |
$this ->temperature = $temperature ; |
59 |
$this ->humidity = $humidity ; |
62 |
public function display() { |
63 |
echo "温度:" . $this ->temperature . "; 湿度:" . $this ->humidity . "%\n" ; |
66 |
class StatistionsDisplay implements Observer, DisplayElement { |
71 |
public function __construct(Subject $weatherData ) { |
72 |
$this ->weatherData = $weatherData ; |
73 |
$weatherData ->registerObserver( $this ); |
75 |
public function update( $temperature , $humidity , $pressure ) { |
76 |
$this ->temperature = $temperature ; |
77 |
$this ->humidity = $humidity ; |
78 |
$this ->pressure = $pressure ; |
81 |
public function display() { |
82 |
echo "温度:" . $this ->temperature . "; 湿度:" . $this ->humidity . "%; 气压:" . $this ->pressure . "\n" ; |
85 |
$weatherData = new WeatherData(); |
86 |
$currentDisplay = new CurrentConditionsDisplay( $weatherData ); |
87 |
$statistionDisplay = new StatistionsDisplay( $weatherData ); |
88 |
$weatherData ->setMeasurements(10, 20, 30); |
89 |
$weatherData ->removeObserver( $currentDisplay ); |
90 |
$weatherData ->setMeasurements(30, 40, 50); |
命令模式
04 |
public function __construct() { |
08 |
public function on() { |
12 |
public function off() { |
18 |
public function execute(); |
21 |
class LightOnCommand implements Command { |
24 |
public function __construct(Light $light ) { |
25 |
$this ->light = $light ; |
28 |
public function execute() { |
33 |
class SimpleRemoteControl { |
36 |
public function __construct() { |
40 |
public function setCommand(Command $command ) { |
41 |
$this ->slot = $command ; |
44 |
public function buttonWasPressed() { |
45 |
$this ->slot->execute(); |
49 |
class RemoteControlTest { |
50 |
public static function main() { |
51 |
$remote = new SimpleRemoteControl(); |
53 |
$lightOn = new LightOnCommand( $light ); |
54 |
$remote ->setCommand( $lightOn ); |
55 |
$remote ->buttonWasPressed(); |
59 |
RemoteControlTest::main(); |
装饰者模式
004 |
* 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 |
006 |
abstract class Beverage { |
007 |
public $description = "Unknown Beverage" ; |
009 |
public function getDescription() { |
010 |
return $this ->description; |
013 |
public abstract function cost(); |
016 |
abstract class CondimentDecorator extends Beverage { |
017 |
//JAVA代码里这里是个抽象类,PHP不允许这么做 |
018 |
public function getDescription() { |
019 |
return $this ->description; |
023 |
class Espresso extends Beverage { |
024 |
public function __construct() { |
025 |
$this ->description = "Espresso" ; |
028 |
public function cost() { |
033 |
class HouseBlend extends Beverage { |
034 |
public function __construct() { |
035 |
$this ->description = "HouseBlend" ; |
038 |
public function cost() { |
043 |
class DarkRoast extends Beverage { |
044 |
public function __construct() { |
045 |
$this ->description = "DarkRoast" ; |
048 |
public function cost() { |
053 |
class Mocha extends CondimentDecorator { |
056 |
public function __construct(Beverage $beverage ) { |
057 |
$this ->beverage = $beverage ; |
059 |
public function getDescription() { |
060 |
return $this ->beverage->getDescription() . ", Mocha" ; |
062 |
public function cost() { |
063 |
return .20 + $this ->beverage->cost(); |
067 |
class Whip extends CondimentDecorator { |
070 |
public function __construct(Beverage $beverage ) { |
071 |
$this ->beverage = $beverage ; |
073 |
public function getDescription() { |
074 |
return $this ->beverage->getDescription() . ", Whip" ; |
076 |
public function cost() { |
077 |
return .10 + $this ->beverage->cost(); |
081 |
class Soy extends CondimentDecorator { |
084 |
public function __construct(Beverage $beverage ) { |
085 |
$this ->beverage = $beverage ; |
087 |
public function getDescription() { |
088 |
return $this ->beverage->getDescription() . ", Soy" ; |
090 |
public function cost() { |
091 |
return .15 + $this ->beverage->cost(); |
095 |
$beverage = new Espresso(); |
096 |
echo $beverage ->getDescription() . "\n" ; |
097 |
$beverage2 = new DarkRoast(); |
098 |
$beverage2 = new Mocha( $beverage2 ); |
099 |
$beverage2 = new Mocha( $beverage2 ); |
100 |
$beverage2 = new Whip( $beverage2 ); |
101 |
echo $beverage2 ->getDescription() . " $" . $beverage2 ->cost() . "\n" ; |
103 |
$beverage3 = new HouseBlend(); |
104 |
$beverage3 = new Soy( $beverage3 ); |
105 |
$beverage3 = new Mocha( $beverage3 ); |
106 |
$beverage3 = new Whip( $beverage3 ); |
107 |
echo $beverage3 ->getDescription() . " $" . $beverage3 ->cost() . "\n" ; |
状态模式
03 |
class GumballMachine { |
06 |
const HAS_QUARTER = 2; |
09 |
public $state = self::SOLD_OUT; |
12 |
public function __construct( $count ) { |
13 |
$this -> count = $count ; |
15 |
$this ->state = self::NO_QUARTER; |
19 |
public function insertQuarter() { |
20 |
if ( $this ->state == self::HAS_QUARTER) { |
21 |
echo "You can't insert another quarter!\n" ; |
22 |
} else if ( $this ->state == self::NO_QUARTER) { |
23 |
$this ->state = self::HAS_QUARTER; |
24 |
echo "You inserted a quarter!\n" ; |
25 |
} else if ( $this ->state == self::SOLD_OUT) { |
26 |
echo "You can't insert a quarter, the machine is sold out!\n" ; |
27 |
} else if ( $this ->state == self::SOLD) { |
28 |
echo "Please wait, we're already giving you a gumball!\n" ; |
33 |
$obj = new GumballMachine(0); |
评论 共0条 (RSS 2.0) 发表评论