天天看點

JavaScript設計模式中政策模式的使用方法政策模式

政策模式

  • 政策模式
    • 政策模式組成組成
    • 多态在政策模式中的展現
      • 多态
    • 政策模式的優點
        • 改造方案一
        • 改造方法二
          • 面向對象的政策模式
          • Javascript 計算獎金版本的政策模式,

政策模式

定義一系列的算法,把它們一個個封裝起來,并且使它們可以互相替換

簡單來說是:定義一系列的算法,把它們各自封裝成政策類,算法被封裝在政策類内部的方法裡,在客戶對 Context 發起請求的時候,Context 總是把請求委托給這些政策對象中間的某一個進行計算。目的将算法的使用與算法的實作分離開來

政策模式組成組成

  1. 政策類:封裝具體的算法,并負責具體的計算過程
  2. 環境類 Context,Context 接受客戶的請求,随後把請求委托給某一個政策類。要做到這一點 Context 要維持對某個政策對象的引用。

多态在政策模式中的展現

每個政策對象負責的算法已被各自封裝在對象内部,當我們發起計算獎金時,它們會傳回不同的計算結果,這正是對象多态性的展現。替換 Context 中目前儲存的政策對象,便能執行不同的算法得到我們想要的結果。

多态

  1. 同一操作作用于不同的對象上面,可以産生不同的解釋和不同的執行結果。換句話說,給不同的對象發送同一個消息的時候,這些對象會根據這個消息分别給出不同的回報。
  2. 多态思想:将“做什麼”和“誰去做以及怎樣去做”分離開來,也就是将“不變的事情”與“可能改變的事物”分離開來。把不變的部分隔離出來,把可變的部分封裝起來,這樣就給予了我們擴充程式的能力,程式看起來是可生長的,也是符合開放-封閉原則的。
  3. 根本作用:通過把過程化的條件分支語句轉化為對象的多态性,進而消除這些條件分支語句。

政策模式的優點

  1. 利用組合、委托、多态等技術和思想,減少多重條件語句
  2. 符合開放封閉原則,把算法封裝在獨立的對象中,使得對象易于切換、易于了解、易于擴充
  3. 代碼邏輯可複用,減少重複工作
    1. 将行為分布在各個對象中,并讓這些對象各自負責自己的行為,這正是面向對象設計的優點。
    2. 例子: 計算績效獎金
const calculateBonus = function (level, salary) {
    if (level == "S") {
    return salary _ 4;
    } else if (level == "A") {
    return salary _ 3;
    } else if (level == "B") {
    return salary \* 2;
    } else {
    return salary;
    }
    };
    console.log(calculateBonus("S", 10000));

           
  1. 缺點:
    • 後期随着績效種類的增加,calculateBonus 函數可能會越來越龐大
    • 實作起來簡單友善,但是 if-else 很多,這些語句需要覆寫所有的邏輯分支
    • 函數缺乏彈性,修改必須深入函數内部邏輯才可以進行修改,不符合開放-封閉原則

改造方案一

  1. 使用組合函數重構代碼
  2. 我們把各種算法封裝到一個個的小函數裡面。
const performanceS = function (salary) {
return salary _ 4;
};
const performanceA = function (salary) {
return salary _ 3;
};

const performanceB = function (salary) {
return salary \* 2;
};

const calulateBonus2 = function (level, salary) {
if (level === "S") {
return performanceS(salary);
} else if (level === "A") {
return performanceA(salary);
} else if (level === "B") {
return performanceB(salary);
} else {
return salary;
}
};
console.log(calulateBonus2("S", 10000));

           
  1. 沒有解決最重要的問題:後期随着績效種類的增加,calculateBonus 函數可能會越來越龐大

改造方法二

面向對象的政策模式
const PS = function () {};
PS.prototype.calculate = function (salary) {
return salary _ 4;
};
const PA = function () {};
PA.prototype.calculate = function (salary) {
return salary _ 3;
};
const PB = function () {};
PB.prototype.calculate = function (salary) {
return salary \* 2;
};

const Bons4 = function () {
this.salary = null;
this.strategy = null; // 績效等級對應的政策對象,
};

Bons4.prototype.setSalary = function (salary) {
this.salary = salary; // 設定原始工資
};
Bons4.prototype.setStrategy = function (strategy) {
this.strategy = strategy; // 設定績效等級對應的政策對象,
};
Bons4.prototype.getBons4 = function () {
return this.strategy.calculate(this.salary); // 設定績效等級對應的政策對象,
};

const bonus4 = new Bons4();
bonus4.setSalary(10000);
bonus4.setStrategy(new PS());
console.log(bonus4.getBons4());
           
Javascript 計算獎金版本的政策模式,

在 JavaScrpt 中,函數也是對象,簡單直接的做法是把 strategy 直接定義為函數

const strategire = {
S: function (salary) {
return salary _ 4;
},
A: function (salary) {
return salary _ 3;
},
B: function (salary) {
return salary \* 2;
},
};
// 2. Context 接受使用者的請求
const calulateBonus3 = function (level, salary) {
return strategire[level](salary);
};
console.log(calulateBonus3("S", 10000));
           

繼續閱讀