由於最近在學策略模式,因此想先跳過建立型設計模式中得適配器模式php
策略模式,顧名思義,就是提供多個策略的模式,用戶在不一樣的狀況下能夠選擇不一樣的策略,好比商場的打折策略(不一樣節假日不一樣的折扣方式),旅遊出行的方式(提供飛行,或者火車,或者大巴的方式)。再進一步講,就是把這些同一個系列的不一樣的算法封裝起來,讓它們可以被客戶自由地使用。算法
Drawn by StarUML
設計模式
大學課程(Lesson)中,有這樣的兩種課程,一種演講(Lecture),一種研討會(Seminar),兩種都須要進行收費,而且有不一樣的收費機制(chargeType),前者是固定收費(FixedCost),後者則是按小時收費(TimeCost)less
CostStrategy.phpui
<?php //CostStrategy類,抽象策略類,Context經過調用這個類來調用該類的具體策略A、B類 //其實是經過抽象類或者接口封裝算法的標識,咱們把封裝算法的接口稱做策略 abstract class CostStrategy{ //定義收費策略的抽象方法,課程與收費機制 abstract function cost(Lesson $lesson); abstract function chargeType(); } ?>
TimeCostStrategy.phpthis
<?php //TimeCostStrategy類,至關於UML圖中的ConcreteStrategyA class TimeCostStrategy extends CostStrategy{ //按時長消費,調用上下文中得getDuration()獲取課程時長,並定義每小時消費5 public function cost(Lesson $lesson){ return ($lesson->getDuration() * 5); public function chargeType(){ return 'Hourly rate'; } } ?>
FixedCostStrategy.phpurl
<?php //FixedCostStrategy類,至關於UML圖中得ConcreteStrategyB class FixedCostStrategy extends CostStrategy{ public function cost(Lesson $lesson){ return 30; //固定收費30 } public function chargeType(){ return 'Fixed rate'; } } ?>
lesson.phpspa
<?php //Lesson類,至關於UML圖中得Context上下文類 class Lesson{ public $duration; //訂價策略爲TimeCostStrategy時的時長 public $strategy; public function __construct($duration,CostStrategy $costStrategy){ $this->duration = $duration; $this->strategy = $costStrategy; } public function cost(){ return $this->strategy->cost($this); } public function chargeType(){ return $this->strategy->chargeType(); } public function getDuration(){ return $this->duration; } //其它方法 } ?>
Lecture.php.net
<?php //Lecture類,是對上下文(Lesson)的繼承 //UML圖中沒有標註出上下文的子類,所以設計模式要具體狀況具體分析 class Lecture extends Lesson{ } ?>
Seminar.php設計
<?php //Seminar類,對上下文的繼承 class Seminar extends Lesson{ } ?>
Client.php
<?php //一次性將全部須要用到的類都引用進來 function __autoload($classname){ $classpath = "./".$classname.".php"; if (file_exists($classpath)) { require_once($classpath); } } $Seminar = new Seminar(4,new FixedCostStrategy()); echo 'The cost type is '.$Seminar->chargeType().',and the cost is '.$Seminar->cost(); ?>
上下文(Context)和具體策略(ConcreteStrategy)是鬆耦合關係。所以上下文只知道它要使用某一個實現Strategy接口類的實例,但不須要知道具體是哪個類
策略模式知足「開-閉原則」。當增長新的具體策略時,不須要修改上下文類的代碼,上下文就能夠引用新的具體策略的實例
消除冗餘的if..else...語句
客戶端須要知道每個策略類,而且知道這些類有什麼不一樣,所以要在策略行爲與客戶行爲密切相關的時候才使用這種模式,把策略暴露給客戶
策略模式會產生不少策略,所以開銷問題也是須要考慮的問題
Context與Strategy之間沒必要要的通訊開銷。ConcreteStrategy類共享Strategy,所以須要實現Strategy中的全部抽象方法,若是有的具體策略類比較簡單,但仍是必需要去實現它的抽象方法,所以會增長沒必要要的開銷