系列目录: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
,而且这个属性是一个对象数据类型的值。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 的几种方法
let proto = {a:1}
let propertiesObject = {
b: {
value: 2
}
}
let obj = Object.create(proto, propertiesObject)
console.log(obj.__proto__ === proto); // true
复制代码
// 方法继承
let proto = function() {}
proto.prototype.excute = function() {}
let child = function() {}
// 让child 继承proto的全部原型方法
child.prototype = new proto()
复制代码
let Foo = function() {}
console.log(Foo.prototype.__proto__ === Object.prototype); // true
复制代码
prototypeObj.isPrototypeOf(obj)
复制代码
contructor.prototype是否出如今obj的原型链上
obj instanceof contructor
复制代码
Object.getPrototypeOf(obj) 方法返回指定对象obj的原型(内部[[Prototype]]属性的值)
Object.getPrototypeOf(obj)
复制代码
设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另外一个对象或 null
var obj = {}
var prototypeObj = {}
Object.setPrototypeOf(obj, prototypeObj)
console.log(obj.__proto__ === prototypeObj) // true
复制代码
仓库源代码: JavaScript-DesignPatterns