一、工厂模式
工厂模式,将 new 操作单独封装。遇到 new 时,就要考虑是否该使用工厂模式。对于工厂模式的理解,可以举例。你去购买汉堡,直接点餐、取餐,不会自己亲手做。商店要封装做汉堡的工作,做好直接给买者。工厂模式的设计原则验证,构造函数和创建者分离,符合开放封闭原则。工厂模式的代码,如下所示: class Product { constructor(name) { this.name = name } init() { alert('init') } fun1() { alert('fun1') } fun2() { alert('fun3') } } class Creator { create(name) { return new Product(name) } } // 测试 let creator = new Creator() let p = creator.create('p1') p.init() p.fun1()二、单例模式
单例模式,系统中被唯一使用,一个类只有一个实例。对于单例模式,常见的示例,比如登录框、购物车、vuex 和 redux 中的 store 等等。单例模式需要使用到 java 的特性 private。ES6 中没有,Typescript 除外,只能用 java 代码来演示 UML 图的内容。单例模式的设计原则验证,符合单一职责原则,只实例化唯一的对象。没法具体开放封闭原则,但是绝对不违反开放封闭原则。单例模式的代码,如下所示:
class SingleObject { login() { console.log('login...') } } SingleObject.getInstance = (function () { let instance return function () { if (!instance) { instance = new SingleObject(); } return instance } })() // 测试 let obj1 = SingleObject.getInstance() obj1.login() let obj2 = SingleObject.getInstance() obj2.login() console.log(obj1 === obj2)单例模式与登录框的结合的代码,如下所示:
class LoginForm { constructor() { this.state = 'hide' } show() { if (this.state === 'show') { alert('已经显示') return } this.state = 'show' console.log('登录框已显示') } hide() { if (this.state === 'hide') { alert('已经隐藏') return } this.state = 'hide' console.log('登录框已隐藏') } } LoginForm.getInstance = (function () { let instance return function () { if (!instance) { instance = new LoginForm(); } return instance } })() // 一个页面中调用登录框 let login1 = LoginForm.getInstance() login1.show() // login1.hide() // 另一个页面中调用登录框 let login2 = LoginForm.getInstance() login2.show() // 两者是否相等 console.log('login1 === login2', login1 === login2)三、适配器模式
适配器模式,旧接口格式和使用者不兼容,中间加一个适配转换接口。对于适配器模式的理解,可以举例。比如在去香港旅游的时候,使用的插头和内地的插头不一样,需要使用转换器进行转换,才可以使用。对于适配器模式的使用场景,封装旧接口,vue computed 等等。适配器模式的设计原则验证,将旧接口和使用者进行分离,符合开放封闭原则。适配器模式的代码,如下所示:
class Adaptee { specificRequest () { return '香港标准接口' } } class Target { constructor() { this.adaptee = new Adaptee() } request () { let info = this.adaptee.specificRequest() return `${info} - 转换器 - 内地标准插头` } } // 测试 let target = new Target() let res = target.request() console.log(res)四、装饰器模式
装饰器模式,为对象添加新功能,不改变其原有的结构和功能。对于装饰器模式的理解,可以举例。在手机上可以套上一个手机壳,不会影响手机的正常使用功能,可以给手机起到装饰的作用,并且保护手机不受到伤害。对于装饰器模式的应用场景,比如 ES7 装饰器,core-decorators 等等。装饰器模式的设计原则验证,将现有对象和装饰器进行分离,两者独立存在,符合开放封闭原则。装饰器模式的代码,如下所示:
class Circle { draw () { console.log('画一个圆形') } } class Decorator { constructor (circle) { this.circle = circle } draw () { this.circle.draw() this.setRedBorder(circle) } setRedBorder(circle) { console.log('设置红色边框') } } // 测试代码 let circle = new Circle() circle.draw() let des = new Decorator(circle) des.draw()装饰器模式在 ES7 装饰器中应用的代码,如下所示:
function log(target, name, descriptor) { var oldValue = descriptor.value; descriptor.value = function() { console.log(`Calling ${name} with`, arguments); return oldValue.apply(this, arguments); }; return descriptor; } class Math { @log add(a, b) { return a + b; } } const math = new Math(); const result = math.add(2, 4); console.log('result', result);装饰器模式在 core-decorators 中应用的代码,如下所示:
import { deprecate } from 'core-decorators'; class Person { @deprecate facepalm() {} @deprecate('We stopped facepalming') facepalmHard() {} @deprecate('We stopped facepalming', { url: 'http://knowyourmeme.com/memes/facepalm' }) facepalmHarder() {} } let person = new Person(); person.facepalm(); person.facepalmHard(); person.facepalmHarder();