iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 3
1
自我挑戰組

來讀設計模式:Junior developer 跟大家一起練功系列 第 11

Day11: Strategy 模式2

今天我們繼續談 strategy 模式。

實作 strategy 模式

DAY10 提到的案例,我們今天來用程式碼來簡單實作一下:

實際的程式碼

首先,先(使用 Java)實作 TaskController & SalesOrder

class TaskController {
    public void proccess() {
        // Controller 的一些操作
        // 取得所在國家資訊等等
    		CalcTax myTax;
    		myTax = getTaxRuleForCountry();
    		SalesOrder mySO = new SalesOrder();
    		mySO.process(myTax);
  	}
  	public CalcTax getTaxRuleForCountry() {
      	// 開發時,需要實際取得所在國的稅務規則
      	// 也可以放在 config 檔中
      	// 這裡先回傳 AmericaTax
      	return new AmericaTax();
    }
  
  	// SalesOrder 類別
  	public class SalesOrder {
    		public void process(CalcTax taxToUse) {
          	int itemNum = 0;
          	int price = 0;
          	// 商品價格的商務邏輯運算
          	// ...
          	// 計算稅額
          	double tax = taxToUse.taxAmount(itemNum, price);
          	
        }
  	}
}

再來,我們來看 CalcTax 與其衍生的不同國家的計算稅額類別:

// CalcTax 抽象類別
abstract class CalcTax {
    abstract public double taxAmount (
        int itemNum,
        int price
    );
}
class AmericaTax {
  	public double taxAmount (
    		int itemNum,
        int price
    ) {
      	// 實作美國稅額計算
      	// 先 return 0
      	return 0.0;
    }
}
class FranceTax {
  	public double taxAmount (
    		int itemNum,
        int price
    ) {
      	// 實作法國稅額計算
      	// 先 return 0
      	return 0.0;
    }
}

這樣就算實作完我們的這個案例了!(當然內部的註解部分需要填充商務邏輯的細節進去)

這樣好處在哪

首先,第一個優點是提高內聚;第二,提高程式碼的靈活度,因為當有新的國家需要新增相對的稅額計算,我們只需要再從 CalcTax 衍生出新類別實作即可。

第三,這讓職責的轉移變得更加容易。若是使用「類別再利用」的繼承方式,我們就必須在 TaskController 決定我們該使用哪一個 SalesOrder 物件;使用上述的方法,我們的 SalesOrder 維持不變,而其中要使用到哪種 CalcTax 的衍生類別,可以由 TaskControllerSalesOrder 決定,其中後者也許需要有 config 檔協助確定。

第四,從 SalesOrder 來看,它用了聚合代替繼承。被包含的類別(CalcTax 的衍生類別們)如何處理變化,SalesOrder 並不關心。

Strategy 模式的定義

GoF 如是說:

(Strategy 模式)定義一系列的演算法,把它們一個個封裝起來,並且使它們可以互相抽換。Strategy 模式使演算法可獨立於使用它的客戶而變化。

此模式建立於幾項原則之上。

  • 物件都具有職責
  • 這些職責不同的具體實作都是透過多型完成
  • 把概念上相同但有不同實作方式的演算法加以管理

Strategy 模式的特徵

Strategy 模式的關鍵特徵如下表

項目 描述
意圖 可以根據上下文使用不同的商務邏輯或演算法
問題 對所需演算法的選擇取決於發出請求的客戶或者需要處理的資料而定
解決方案 把演算法的選擇與演算法的實作分離開來。允許根據上下文進行選擇
參與者與協作者 1. Strategy 指定了如何使用不同的演算法2. 各 ConcreteStrategy 實作不同的演算法3. 上下文透過類型為 Strategy 的參照使用具體的 ConcreteStrategy
效果 1. 定義了一系列的演算法2. 可以不用 switch-case3. 要使用哪種 ConcreteStrategy 取決於上下文給予的狀態資訊
實作 讓使用演算法的類別 (Context) 包含一個抽象類別 (Strategy)。該抽象類別有個 abstract method 指定演算法,每個衍生的類別依各自需求來實作演算法

以下為 UML 圖。

接下來

明天我們會再繼續介紹下一個設計模式:Bridge 模式。

See ya!


上一篇
DAY10: Strategy 模式1
下一篇
DAY12: Bridge 模式1
系列文
來讀設計模式:Junior developer 跟大家一起練功22

尚未有邦友留言

立即登入留言