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操做。例如在咱们点击登陆后出现的登陆浮窗,不管点击多少次登陆按钮,这个浮窗都只会被建立一次。这里就能够用惰性单例模式来建立。闭包

惰性单例是值在须要的时候才建立对象实例。app

<!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

相关文章
相关标签/搜索