JavaScript 設計模式解析【1】——建立型設計模式

系列目錄:javascript

工廠模式

工廠模式是用來建立對象的一種設計模式。html

它不會暴露建立對象的具體邏輯,而是將邏輯封裝在一個函數中,那麼這個函數便成爲了工廠,同時根據抽象程度的不一樣分爲簡單工廠工廠方法java

簡單工廠模式

經過一個工廠建立一種對象類的實力。主要用來建立同一類的對象。git

// 簡單工廠模式
// Pet 類
class Pet {
  // 構造函數
  constructor(props) {
    this.species = props.species;
    this.sound = props.sound;
  }

  // 靜態實例建立方法
  static getProps(pet) {
    switch (pet) {
      case 'dog':
        return new Pet({species: 'dog', sound: 'woof'});
      case 'cat':
        return new Pet({species: 'cat', sound: 'meow'});
      case 'bird':
        return new Pet({species: 'bird', sound: 'chirping'});
      }
  }
}

let Adog = Pet.getProps('dog');
console.log(Adog.sound); // woof
let Acat = Pet.getProps('cat');
console.log(Acat.sound); // meow
let Abird = Pet.getProps('bird');
console.log(Abird.sound); // chirping
複製代碼

簡單工廠讓咱們只須要傳遞一個參數給工廠函數便可獲取到對應的實例對象,而不須要知道細節,但簡單工廠模式只能用於對象數量少,對象建立邏輯不復雜的狀況。github

工廠方法模式

工廠方法模式讓咱們將建立實例的過程推遲到了子類中,這樣咱們的核心類就變成的抽象類,而且將構造函數和建立者分離,對 new 操做進行了封裝。設計模式

// 工廠方法模式
class Pet {
  constructor(species = '', sound = '') {
    this.species = species;
    this.sound = sound;
  }
}

// 工廠子類
class PetShop extends Pet {
  constructor(species, sound) {
    super(species, sound);
  }
  create(pet) {
    switch (pet) {
      case 'dog':
        return new PetShop('dog','woof');
      case 'cat':
        return new PetShop('cat','meow');
      case 'bird':
        return new PetShop('bird','chirping');
      }
  }
}

let thePetShop = new PetShop();
// 經過建立者的方法進行實例建立
let shopDog = thePetShop.create('dog');
console.log(shopDog.sound); // woof
let shopCat = thePetShop.create('cat');
console.log(shopCat.sound); // meow
let shopBird = thePetShop.create('bird');
console.log(shopBird.sound); // chirping
複製代碼

咱們能夠將工廠方法看作一個實例化對象的工廠,它只作實例化對象這一件事。瀏覽器

總結

  • 工廠模式將構造函數和建立者分離
  • 符合開放封閉原則

單例模式

單例模式的核心思想是:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點bash

JavaScript 的單例模式不一樣於面向對象的應用,而在實際的開發中卻有不少用途,例如提升頁面性能,避免沒必要要的DOM操做。例如在咱們點擊登陸後出現的登陸浮窗,不管點擊多少次登陸按鈕,這個浮窗都只會被建立一次。這裏就能夠用惰性單例模式來建立。markdown

惰性單例是值在須要的時候才建立對象實例。閉包

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Single Pattern</title>
</head>
<body>
  <button id="btn">點我登陸</button>
  <script> class Login { createLayout() { console.log('invoked') let theDiv = document.createElement('div'); theDiv.innerHTML = '我是浮窗' document.body.appendChild(theDiv) theDiv.style.display = 'none' return theDiv } } class Single { getSingle(fn) { let result; return function () { return result || (result = fn.apply(this, arguments)) } } } let theBtn = document.getElementById('btn') let single = new Single() let login = new Login() // 因爲閉包, createLoginLayer 對 result 的引用, 因此當single.getSingle 函數執行完以後,內存中並不會銷燬 result // 以後點擊按鈕是,根據 createLoginLayer 函數的做用域鏈中已經存在result,因此直接返回result let createLoginLayer = single.getSingle(login.createLayout) theBtn.onclick= function() { let layout = createLoginLayer() layout.style.display = 'block' } </script>
</body>
</html>
複製代碼

此時咱們能夠連續點擊登陸按鈕,但 invoked只會輸出一次,表明着實例只建立了一次而且以後使用的都是惟一的那個實例。

總結

  • 單例模式的主要思想: 實例已經建立,就直接返回,反之,則建立新的實例。
  • 符合開放封閉原則。

原型模式

經過原型實例指定建立對象的類型,而且經過拷貝原型來建立新的對象。

在 JavaScript 中,實現原型模式的方法是Object.create方法,經過使用現有的對象來提供新建立的對象的_proto_

  • 每個函數數據類型(普通函數,類)都有一個天生自帶的屬性:prototype,而且這個屬性是一個對象數據類型的值。
  • 而且在prototype上瀏覽器天生添加了一個構造函數constructor,屬性值是當前函數(類)自己。
  • 每個對象數據類型葉天生自帶一個屬性proto,屬性值是當前實例所屬類的原型。
var prototype = {
  name: 'Reaper',
  getName: function() {
    return this.name;
  }
}
// 同時注意 Object.create爲淺拷貝
var obj = Object.create(prototype, 
  {
    skill: {value: 'FE'}
  }
)

console.log(obj.getName()); //Reaper
console.log(obj.skill); // FE
console.log(obj.__proto__ === prototype); //true

複製代碼

prototype 的幾種方法

1.Object.create()方法

let proto = {a:1}
let propertiesObject = {
  b: {
    value: 2
  }
}

let obj = Object.create(proto, propertiesObject)
console.log(obj.__proto__ === proto); // true
複製代碼

2.方法繼承

// 方法繼承
let  proto = function() {}
proto.prototype.excute = function() {}
let child = function() {}

// 讓child 繼承proto的全部原型方法
child.prototype = new proto()
複製代碼

3.函數對Object的默認繼承

let Foo = function() {}
console.log(Foo.prototype.__proto__ === Object.prototype); // true
複製代碼

4.isPrototypeOf

prototypeObj.isPrototypeOf(obj)
複製代碼

5.instanceof

contructor.prototype是否出如今obj的原型鏈上

obj instanceof contructor
複製代碼

6.getPrototypeOf

Object.getPrototypeOf(obj) 方法返回指定對象obj的原型(內部[[Prototype]]屬性的值)

Object.getPrototypeOf(obj)
複製代碼

7.setPrototypeOf

設置一個指定的對象的原型 ( 即, 內部[[Prototype]]屬性)到另外一個對象或 null

var obj = {}
var prototypeObj = {}
Object.setPrototypeOf(obj, prototypeObj)
console.log(obj.__proto__ === prototypeObj)  // true
複製代碼

倉庫源代碼: JavaScript-DesignPatterns

相關文章
相關標籤/搜索