策略模式(Strategy Pattern)定義了一組策略,分別在不同類中封裝起來,每種策略都可以根據當前場景相互替換,從而使策略的變化可以獨立於操作者。
大家都寫過這樣的代碼
if (conditionA) { 邏輯1 } else if (conditionB) { 邏輯2 } else if (conditionC) { 邏輯3 } else { 邏輯4 }
這種代碼雖然寫起來簡單,但是很明顯違反了面向對象的 2 個基本原則:
單一職責原則(一個類應該只有一個發生變化的原因):因為之后修改任何一個邏輯,當前類都會被修改
開閉原則(對擴展開放,對修改關閉):如果此時需要添加(刪除)某個邏輯,那么不可避免的要修改原來的代碼
因為違反了以上兩個原則,尤其是當 if-else 塊中的代碼量比較大時,后續代碼的擴展和維護就會逐漸變得非常困難且容易出錯
if-else 不超過 2 層,塊中代碼 1~5 行,直接寫到塊中,否則封裝為方法
if-else 超過 2 層,且塊中代碼超過 3 行,盡量使用策略模式
下面是PHP策略模式的demo,需求是當需要發送各種通知的時候 , 比如發送短信 ,發送郵件 , 發送微信通知 等等 ,可以拆分成一個個策略
<?php //短信類 class Sms{ public function send(){ echo "send sms"; } } //郵件類 class Email{ public function send(){ echo "send email"; } } //微信類 class Weixin{ public function send(){ echo "send weixin"; } } //存儲上面策略的工廠 class Factory{ public $products=array(); public function get($type){ return $this->products[$type]; } public function register($type){ $class=ucfirst($type); $this->products[$type]=new $class; } } //控制器代碼 class Controller{ public $types=array("sms","email","weixin"); public $factory=null; public function __construct(){ //先生成出所有策略的對象 $this->factory=new Factory(); foreach($this->types as $t){ $this->factory->register($t); } } public function doAction(){ //根據傳遞的type參數 , 選擇使用哪一個策略 $type="sms"; $notice=$this->factory->get($type); $notice->send(); $type="email"; $notice=$this->factory->get($type); $notice->send(); } } $c=new Controller(); $c->doAction();
