JavaScript設計模式—策略模式

定義

定義一系列算法,把它們一個個封裝起來,而且使它們能夠相互替換。一個基於策略模式的程序至少有兩部分組成:web

  1. 策略類:封裝具體的算法,並負責具體的計算過程
  2. 環境類 Context: Context接受客戶請求,隨後將請求委託給策略類

真實世界類比

策略模式

假如你須要前往機場。 你能夠選擇乘坐公共汽車、 預定出租車或騎自行車。 這些就是你的出行策略。 你能夠根據預算或時間等因素來選擇其中一種策略。算法

模式實現-計算獎金

這裏咱們以年終獎的計算爲例進行實現:設計模式

假設績效爲S的人年終獎有 4 倍工資;A的人年終獎有 3 倍工資;B的人年終獎有 2 倍工資。markdown

按照策略模式的基本組成咱們進行分解:app

// 第一步: 封裝策略類
const strategies = {
  S: salary => {
    return salary * 4;
  },
  A: salary => {
    return salary * 3;
  },
  B: salary => {
    return salary * 2;
  }
};

// 第二步:這裏咱們用calculateBonus函數充當Context來接收用戶請求
const calculateBonus = (level, salary) => {
  return strategies[level](salary);
};

console.log(calculateBonus("S", 20000)); // 輸出:80000
console.log(calculateBonus("A", 10000)); // 輸出:30000
複製代碼

更廣義的「算法」

策略模式指的是定義一系列算法。但在實際的開發中,咱們一般會把算法的含義擴散開來,使策略模式也能夠用來封裝一系列的業務規則。只要這些業務規則指向的目標一致,並且能夠被替換使用。dom

模式實現-表單校驗

在 web 應用中,涉及表單的部分幾乎都離不開校驗。函數

假設咱們正在編寫一個註冊頁面,在點擊註冊按鈕前,須要校驗如下幾條邏輯:oop

  • 用戶名不能爲空
  • 密碼長度很多於 6 位
  • 手機號必須符合格式
// 第一步: 封裝策略類
const strategies = {
  isNonEmpty: (value, errorMsg) => {
    if (value === "") {
      return errorMsg;
    }
  },
  minLength: (value, errorMsg) => {
    if (value.length < 6) {
      return errorMsg;
    }
  },
  isMobile: (value, errorMsg) => {
    if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
      return errorMsg;
    }
  }
};

// 第二步:封裝Validator類充當Context來接收用戶請求並委託給strategy對象
class Validator {
  constructor() {
    this.cache = [];
  }
  add(dom, strategy, errorMsg) {
    this.cache.push(() => {
      const args = [dom.value, errorMsg];
      return strategies[strategy].apply(dom, args);
    });
  }
  start() {
    this.cache.forEach(fn => {
      const msg = fn();
      if (msg) {
        return msg;
      }
    });
  }
}

// 使用
const registerForm = document.getElementById("registerForm");
function validataFunc() {
  const validator = new Validator();
  validator.add(registerForm.userName, "isNonEmpty", "用戶名不能爲空");
  validator.add(registerForm.password, "minLength", "密碼長度不能少於6位");
  validator.add(registerForm.phone, "isMobile", "手機號碼格式不正確");
  const error = validator.start();
  return error;
}
registerForm.onsubmit = () => {
  const errorMsg = validataFunc();
  if (errorMsg) {
    alert(errorMsg);
    return false;
  }
};
複製代碼

能夠看到,咱們僅僅經過配置的方式就完成了一個表單的校驗。this

小結

在JavaScript語言的策略模式中,策略類每每被函數所代替,這時策略模式就成了一種「隱形」的模式。儘管如此,從根本上理解策略模式的理念不只讓咱們對模式有這更透徹的瞭解,也能夠讓咱們明白使用函數的好處。spa

參考

相關文章
相關標籤/搜索