工程師在工作一段時間後,隨著專案規模的擴大,難免會發現一些可以優化和調整的項目。此時,我們常聽到的「重構」就會浮上檯面。不過由於重構的內容與方法有很多,我目前也不打算開一個系列來詳細介紹,因此在這裡我將專注於介紹一個無論是在重構還是一般功能設計時都可能會用到的內容——「策略模式」。
策略模式(Strategy Pattern)是一種行為型設計模式,其目的是定義一系列函數,並將每個函數封裝成策略,以便它們可以互相替換。聽起來可能有點複雜,不如我們直接來看一個例子吧。
假設我們現在想要執行的策略類型是計算,接著我們可以計算的策略,例如加減乘除。
interface Strategy {
public function execute($a, $b);
}
// 設定策略種類
class Addition implements Strategy {
public function execute($a, $b) {
return $a + $b;
}
}
class Subtraction implements Strategy {
public function execute($a, $b) {
return $a - $b;
}
}
// 使用策略
class Context {
private $strategy;
public function __construct(Strategy $strategy) {
$this->strategy = $strategy;
}
public function setStrategy(Strategy $strategy) {
$this->strategy = $strategy;
}
public function executeStrategy($a, $b) {
return $this->strategy->execute($a, $b);
}
}
// 創建實例去使用
$context = new Context(new Addition());
echo $context->executeStrategy(5, 3); // 輸出 8
$context->setStrategy(new Subtraction());
echo $context->executeStrategy(5, 3); // 輸出 2
$context->setStrategy(new Multiplication());
echo $context->executeStrategy(5, 3); // 輸出 15
唯一且重要的關鍵在於,這些策略必須具有相同的輸入和輸出類型。這樣可以在選擇策略時保持一致性,讓使用過程更加方便。
此外,在實作時,我們可以先將所有函數統一為相同的輸入和輸出模式,然後再將它們逐步整合成策略模式。這樣的過程會使得實現更加簡單明瞭,降低錯誤的可能性。
if-else
或 switch
判斷式,從而使程式碼更加簡潔明瞭。使用策略模式的情境通常是因為存在許多相似需求(如相同的輸入輸出)或相似的處理方式,這會導致維護困難和易讀性差。通過採用策略模式,可以有效減少程式碼重複,從而提高靈活性和可維護性。