《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) 发表评论