JavaScript經常使用的設計模式

前言

設計模式幾十種,閱讀了《JavaScript設計模式與開發實踐》這本書後,我的感受js就是圍繞對象來設計的,發現平常寫代碼能用上的並很少,下面是經常使用的幾種設計模式。javascript

個人github,歡迎 star前端

模式列表

  • 單例模式
  • 策略模式
  • 模板方法模式
  • 職責鏈模式
  • 發佈訂閱模式

設計模式

單例模式

單一模式的核心是確保只有一個實例,並提供全局訪問,在 JS 開發中,常常把用一個對象包裹,這樣減小了全局變量的污染,好比 var a = {}。java

普通寫法:git

// 每次點擊點擊按鈕,都會建立一個 div
  var createLayer1 = (function () {
    var div = document.createElement('div');
      div.innerHTML = '我是內容';
      div.style.display = 'none';
      document.body.appendChild(div);
      return div;
  })()

  document.getElementById('#btn').onclick = function () {
    var layer1 = createLayer1();
    layer1.style.display = 'block';
  }

單例模式:github

//實例對象老是在咱們調用方法時才被建立,而不是在頁面加載好的時候就建立。  
  // 這樣就不會每次點擊按鈕,都會建立一個 div 了
  var createLayer2 = function () {
    var div;
    return function () {
      if (!div) {
        document.createElement('div');
        div.innerHTML = '我是內容';
        div.style.display = 'none';
        document.body.appendChild(div);
      }
      return div;
    }
  }

  document.getElementById('#btn').onclick = function () {
    var layer2 = createLayer2();
    layer2.style.display = 'block';
  }

策略模式

策略模式代碼很是優雅,最喜歡模式之一,也很便於修改,請看代碼。設計模式

普通模式:app

var awardS = function (salary) {
    return salary * 4
  };

  var awardA = function (salary) {
    return salary * 3
  };

  var awardB = function (salary) {
    return salary * 2
  };

  var calculateBonus = function (level, salary) {
    if (level === 'S') {
      return awardS(salary);
    }
    if (level === 'A') {
      return awardA(salary);
    }
    if (level === 'B') {
      return awardB(salary);
    }
  };

  calculateBonus('A', 10000);

策略模式:socket

var strategies = {
    'S': function (salary) {
      return salary * 4;
    },
    'A': function (salary) {
      return salary * 3;
    },
    'B': function (salary) {
      return salary * 2;
    }
  }

  var calculateBonus = function (level, salary) {
    return strategies[level](salary);
  }

  calculateBonus('A', 10000);

模板方法模式

模板方法模式使用了原型鏈的方法,封裝性好,複用性差。this

var Coffee = function () {

  };
  Coffee.prototype.boilWater = function () {
    // todo
    console.log('把水煮沸');
  };
  Coffee.prototype.brewCoffee = function () {
    // todo
    console.log('衝咖啡');
  };
  Coffee.prototype.pourInCup = function () {
    // todo
    console.log('把咖啡倒進杯子');
  };
  Coffee.prototype.addSugarAndMilk = function () {
    // todo
    console.log('加糖和牛奶');
  };
  Coffee.prototype.init = function () {
    this.boilWater();
    this.brewCoffee();
    this.pourInCup();
    this.addSugarAndMilk();
  }

  var coffee = new Coffee();
  coffee.init();

職責鏈模式

沒錯,我剛開始寫第一個項目時候就這麼嵌套的,重複代碼太多,邏輯太亂,維護下太差。prototype

var order = function (orderType, pay, stock) {
    // 500 元定金模式
    if (orderType === 1) {
      if (pay === true) {
        console.log('500元定金預購,獲得100元優惠券');
      } else {
        if (stock > 0) {
          console.log('普通購買,無優惠券');
        } else {
          console.log('手機庫存不足');
        }
      }
    // 200 元定金模式
    } else if (orderType === 2) {
      if (pay === true) {
        console.log('200元定金預購,獲得50元優惠券');
      } else {
        if (stock > 0) {
          console.log('普通購買,無優惠券');
        } else {
          console.log('手機庫存不足');
        }
      }
    // 沒有定金模式  
    } else if (orderType === 3) {
      if (stock > 0) {
        console.log('普通購買,無優惠券');
      } else {
        console.log('手機庫存不足');
      }
    } 
  }

  order(1, true, 500);

職責鏈,一系列可能處理請求的對象被鏈接成一條鏈,請求在這些對象之間依次傳遞,直到遇到一個能夠處理它的對象,減小了不少重複代碼。

var order500 = function (orderType, pay, stock) {
    if (orderType === 1 && pay === true) {
      console.log('500元定金預購,獲得100元優惠券');
    } else {
      order200(orderType, pay, stock);
    }
  }

  var order200 = function (orderType, pay, stock) {
    if (orderType === 2 && pay === true) {
      console.log('200元定金預購,獲得50元優惠券');
    } else {
      orderNormal(orderType, pay, stock);
    }
  }

  var orderNormal = function (orderType, pay, stock) {
    if (stock > 0) {
      console.log('普通購買,無優惠券');
    } else {
      console.log('手機庫存不足');
    }
  }

  order500(1, true, 500);
  order500(1, false, 500);
  order500(2, true, 500);

發佈-訂閱模式

發佈訂閱模式,顧名思義,就是一個發佈消息,一個監聽消息,當有消息接收時處理消息。

// js前端
  window.onload = function () {
    var socket = io.connect('http://localhost:20122?token=abc');
    socket.on('connect', function() {
      socket.emit('message', ':chat socket')
    });
    socket.on('message', function(data) {
      alert(data)
    })
  };

  // 服務端
  io.on('connection', function (socket) {
    socket.on('chat message', function (msg) {
      console.log('receive a message: ' + msg)
      io.emit('chat message', msg);
    });
  })

能夠參考個人另外一個倉庫地址,一個簡單的實時聊天 demo

參考

相關文章
相關標籤/搜索