沒有戰略的企業就像一艘沒有舵的船,只會在原地轉圈。
Without a strategy, an organization is like a ship without a rudder, going around in circles.
– Joel Ross
設計模式是解決開發時遇到普遍存在(反覆出現)的問題的各種解法。但並不是絕對的,遇到問題才使用解法而不是為了使用而使用。
切記: 不要拿了錘子,看什麼都是釘子
介紹
策略模式屬於行為模式,依照不同的情境制定不同的策略(行為),策略(行為)之間可以互相替換而不受影響。像是行軍打仗時將軍的戰爭策略、不同節日時商家的銷售策略等…
- 目的: 將各種不同的**演算法(策略)**封裝成類別,執行何種策略是由客戶端決定。
情境
巫師們需要根據不同情況施展魔法(策略),保護隊友使用疾疾,護法現身(Expecto Patronum)
,救火用水水噴(Aquamenti)
而卸除對方武器可以使用去去,武器走(Expelliarmus)
。
策略模式中會規範魔法使用的規章(策略介面),魔法的實際應用則是實體策略。使用何種魔法(策略)的依據則是巫師面對的不同景靚。
範例
咒語規章(介面)與咒語(實作)
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
| /** * 咒語介面 */ interface Magic { public function spell(); }
/** * 疾疾,護法現身 */ class ExpectoPatronum implements Magic {
public function spell() { return '疾疾,護法現身!'; } }
/** * 水水噴 */ class Aquamenti implements Magic {
public function spell() { return '水水噴!'; } }
/** * 去去,武器走 */ class Expelliarmus implements Magic {
public function spell() { return '去去,武器走!'; } }
|
巫師
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
| /** * 巫師 */ class Wizard { /** * 使用的魔法(策略) * @var */ protected $_magic;
/** * 切換魔法(策略) * @param Magic $magic */ public function choiceMagic(Magic $magic) { $this->_magic = $magic; }
/** * 施咒 * @return string */ public function spell() { if ($this->_magic == null) { return '完蛋,忘記要用什麼咒語了!'; }
return $this->_magic->spell(); } }
|
使用場景
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
| # 巫師走在路上 $wizard = new Wizard();
echo '巫師走在路上。';
echo '</br>'; echo '</br>'; # 遇到有人被攻擊了,保護他 echo '遇到路人被催狂魔攻擊!' . '</br>'; $wizard->choiceMagic(new ExpectoPatronum()); echo '念咒: ' . $wizard->spell();
echo '</br>'; echo '</br>'; # 遇到屋子燒起來了,滅火 echo '遇到路邊的房子燒起來了!' . '</br>'; $wizard->choiceMagic(new Aquamenti()); echo '念咒: ' . $wizard->spell();
echo '</br>'; echo '</br>'; # 遇到別的巫師拿著魔杖指著你,搶法杖 echo '遇到有人拿著法杖指著你!' . '</br>'; $wizard->choiceMagic(new Expelliarmus()); echo '念咒: ' . $wizard->spell();
|
執行結果
1 2 3 4 5 6 7 8 9 10
| 巫師走在路上。
遇到路人被催狂魔攻擊! 念咒: 疾疾,護法現身!
遇到路邊的房子燒起來了! 念咒: 水水噴!
遇到有人拿著法杖指著你! 念咒: 去去,武器走!
|
討論
由於介面
規範的關係,各種策略間互相切換是不會出問題的,因此策略的使用上非常的靈活且易於擴充。
但若策略數量過多的話會讓維護端帶來額外的開銷。由於策略的實作是在客戶端,因此客戶端應該知道有什麼策略,並且瞭解各種策略之間的區別。
策略模式 VS 工廠模式
若對工廠模式不熟悉的朋友,可到此大概了解一下。
單看類別圖或是描述及用法看起來根本一模一樣,但兩種模式各自著重的點如下:
- 簡單工廠模式是用來建立物件的模式,關注物件如何被產生。
- 策略模式是一種行為模式,關注的是行為的封裝。
簡單的來說,工廠模式著重的是產出類別(巫師),至於類別(巫師)後續做了何種行為則跟他沒關係了。
而策略模式著重的是在策略本身,依照情況使用什麼策略,至於策略怎麼來的。就不是重點了。