设计模式
1. 创建型
1. 原型模式
- 概念
- clone 自己,生成一个对象
- 应用(Object.create)
//基于原型创建一个对象 var prototype = { getName: function() { return this.first + ' ' + this.last }, say: function() { console.log('hello') } }
//基于原型创建 var x = Object.create(prototype) x.first = 'A' x.last = 'B' console.log(y.getName()) y.say()
- JS 中的原型 prototype
- 可以理解为 ES6 class 的一种底层原理
- 而 class 是实现面向对象的基础,并不是服务于某个模式
- ES6 全面普及后,可能会忽略 prototype
2. 结构型
2.1 桥接模式
-
概念
- 用于把抽象化与实现化解耦,是的二者可以独立变化
-
演示
class ColorShape { yellowCircle() { console.log('yellow circle') } redCircle() { console.log('red circle') } yellowTriangle() { console.log('yellow triangle') } redTriangle() { console.log('red triangle') } } let cs = new ColorShape() cs.redCircle() cs.redTriangle() cs.yellowCircle() cs.yellowTriangle()
-
设计原则
- 抽象和实现分离,解耦
- 符合开放分离原则
2.2 组合模式
-
概念
生成树形结构,“整体-部分关系”。让整体和部分都具有一致的操作方式 -
代码演示
//虚拟DOM(vNode) <div id="div1" class="container"> <p>123</p> <p>456</p> </div>
{ tag:'div', attr:{ id:'div1', className:'container' }, children:[ { tag:'p', attr:{}, children:['123'] },{ tag:'p', attr:{}, children:['456'] } ] }
-
设计原则
- 将整体和单个节点的操作抽象出来,符合开放封闭原则
2.3 享元模式
-
概念
- 共享内存(主要考虑内存,而非效率)
- 相同的数据,共享使用
-
代码演示
<div id="div1"> <a href="#">a1<a/> <a href="#">a2<a/> <a href="#">a3<a/> <a href="#">a4<a/> <a href="#">a5<a/> </div> <script> var div1 = document.getElementById('div1') div1.addEventListener('click',function(e){ var target = e.target if(target.nodeName === 'A'){ alert(alert.innerHTML) } }) </script>
-
设计原则
- 将相同的部分抽象出来,符合开放封闭原则
3. 行为型
3.1 策略模式
- 概念
- 不同策略分开处理,避免出现大量 if…else
-
代码验证
class User { constructor(type) { this.type = type } buy() { if (this.type === 'ordinary') { console.log('普通用户购买') } else if (this.type === 'member') { console.log('会员用户购买') } else if (this.type === 'vip') { console.log('VIP用户购买') } } } //测试 var u1 = new User('ordinary') u1.buy() var u2 = new User('member') u2.buy() var u3 = new User('vip') u3.buy()
//改进 class OrdinaryUser { buy() { console.log('普通用户购买') } } class MemberUser { buy() { console.log('会员用户购买') } } class VipUser { buy() { console.log('VIP 用户购买') } } //测试 var u1 = new OrdinaryUser() u1.buy() var u2 = new MemberUser() u2.buy() var u3 = new VipUser() u3.buy()
-
设计原则
- 不同策略分开处理,符合开放封闭原则
3.2 模板方法模式
-
概念
-
代码验证
class Action { handle() { handle1() handle2() handle3() } handle1() { console.log('1') } handle21() { console.log('2') } handle3() { console.log('3') } }
-
设计原则
3.3 职责链模式
- 概念
- 异步操作可能分为多个职责角色来完成
- 吧这些角色都分开,然后用一个链串起来
- 将发起者和各个处理者进行隔离
- JS 中的链式操作
- jQuery 的链式操作
- Promise.then 的链式操作
-
代码验证
//请假审批,需要组长、经理、总监分布审批 class Action { constructor(name) { this.name = name this.nextActoin = null } setNextAction(action) { this.nextAction = action } handle() { console.log(`${this.name}审批`) if (this.nextAction != null) { this.nextAction.handle() } } } //测试 let a1 = new Action('组长') let a2 = new Action('经理') let a3 = new Action('总监') a1.setNextAction(a2) a2.setNextAction(a3) a1.handle()
-
设计原则
- 发起者于各个处理者进行隔离
- 符合开放封闭原则
3.4 命令模式
- 概念
- 执行命令时,发布者和执行者分开
-
代码验证
class Receiver { exec() { console.log('执行') } } class Command { constructor(receiver) { this.receiver = receiver } cmd() { console.log('触发命令') this.receiver.exec() } } class Invoker { constructor(command) { this.command = command } invoke() { console.log('开始') this.command.cmd() } } //士兵 let soldier = new Receiver() //小号手 let trumpeter = new Command(soldier) //将军 let general = new Invoker(trumpeter) general.invoke()
-
JS 中的应用
- 网页富文本编辑器操作,浏览器封装命令对象
- 设计原则
- 命令者与执行对象分开,解耦
- 符合开放封闭原则
3.5 备忘录模式
- 概念
- 随时记录一个对象的状态变化
- 随时可以恢复之间的某个状态(如撤销)
-
代码验证
//状态备忘 class Memento { constructor(content) { this.content = content } getContent() { return this.content } } //备忘列表 class CareTaker { constructor() { this.list = [] } add(memento) { this.list.push(memento) } get(index) { return this.list[index] } } //编辑器 class Editor { constructor() { this.content = null } setContent(content) { this.content = content } getContent() { return this.content } saveContentToMemento() { return new Memento(this.content) } getContentFromMemento(memento) { this.content = memento.getContent() } } let editor = new Editor() let careTaker = new CareTaker() editor.setContent('111') editor.setContent('222') careTaker.add(editor.saveContentToMemento()) //储存 editor.setContent('333') careTaker.add(editor.saveContentToMemento()) //储存 editor.setContent('444') console.log(editor.getContent()) editor.getContentFromMemento(careTaker.get(1)) //撤销 console.log(editor.getContent()) editor.getContentFromMemento(careTaker.get(0)) //撤销 console.log(editor.getContent()) console.log(careTaker.get(1))
-
设计原则
- 状态对象与使用者分开,解耦
- 符合开放封闭原则
3.6 中介者模式
- 概念
- 多个对象能够通过一个对象进行访问
-
代码验证
class Mediator { constructor(a, b) { this.a = a this.b = b } setA() { let number = this.b.number this.a.setNumber(number * 100) } setB() { let number = this.a.number this.b.setNumber(number / 100) } } class A { constructor() { this.number = 0 } setNumber(num, m) { this.number = num if (m) { //如果有中介者 m.setB() } } } class B { constructor() { this.number = 0 } setNumber(num, m) { this.number = num if (m) { m.setA() } } } //测试 let a = new A() let b = new B() let m = new Mediator(a, b) a.setNumber(100, m) console.log(a.number, b.number) b.setNumber(100, m) console.log(a.number, b.number)
-
设计原则
- 符合开放封闭原则
3.7 访问者模式
- 概念
- 将数据操作和数据结构分离
3.8 解释器模式
- 概念
- 描述语言语法如何定义,如何解释和编译