1. 其他模式
1.1 创建型
1.1.1 原型模式
概念
clone 自己,生成一个对象
java 默认有 clone 接口,不用自己实现
JS 中的应用 - 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 ( x. getName ( ) )
x. say ( )
var y = Object. create ( prototype)
y. first = 'C'
y. last = 'D'
console. log ( y. getName ( ) )
y. say ( )
对比 JS 中的原型 prototype
prototype
可以理解为 ES6 class 的一种底层原理
而 class 是实现面向对象的基础
,并不是服务于某个模式
若干年后 ES6 全面普及,大家可能会忽略掉 prototype
但是 Object.create 却会长久存在
1.2 结构型
1.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. yellowCircle ( )
cs. redCircle ( )
cs. yellowTriangle ( )
cs. redTriangle ( )
演示
代码演示
class Color {
constructor ( name) {
this . name = name
}
}
class Shape {
constructor ( name, color) {
this . name = name
this . color = color
}
draw ( ) {
console. log ( `$[this.color.name} ${
this . name} ` )
}
}
let red = new Color ( 'red' )
let yellow = new Color ( 'yellow' )
let circle = new Shape ( 'circle' , red)
circle. draw ( )
let triangle = new Shape ( 'triangle' , yellow)
triangle. draw ( )
1.2.2 组合模式
概念
生成树形结构,表示“整体-部分”关系
让整体和部分都具有一致的操作方式
示例
演示
JS 经典应用中,未找到这么复杂的数据类型
虚拟 DOM 中的 vnode 是这种形式,但数据类型简单
用 JS 实现一个菜单,不算经典应用,与业务相关
< 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' ]
}
]
}
演示
整体和单个节点的操作是一致的
整体和单个节点的数据结构也保持一致
设计原则验证
1.2.3 享元模式
概念
共享内存(主要考虑内存,而非效率)
相同的数据,共享使用
演示
< div id = " div1" >
< a href = " #" > a1</ a>
< a href = " #" > a2</ a>
< a href = " #" > a3</ a>
< a href = " #" > a4</ a>
</ div>
< script>
var div1 = document. getElementById ( 'div1' )
div1. addEventListener ( 'click' , function ( e) {
var target = e. target
if ( e. nodeName === 'A' ) {
alert ( target. innerHTML)
}
} )
</ script>
1.2.4 外观模式
概念
为子系统中的一组接口提供了一个高层接口
使用者使用这个高层接口
示例
UML 类图
场景
function bindEvent ( elem, type, selector, fn) {
if ( fn == null ) {
fn = selector
selector = null
}
}
bindEvent ( elem, 'click' , '#div1' , fn)
bindEvent ( elem, 'click' , fn)
设计原则验证
不符合单一职责原则和开放封闭原则,因此谨慎使用,不可滥用
1.3 行为型
1.3.1 策略模式
概念
不同策略分开处理
避免出现大量 if...else 或者 switch...case
演示
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 ( )
设计原则验证
不同策略,分开处理,而不是混合在一起
符合开放封闭原则
1.3.2 模版方法模式
class Action {
handle ( ) {
handle1 ( )
handle2 ( )
handle3 ( )
}
handle1 ( ) {
console. log ( '1' )
}
handle2 ( ) {
console. log ( '2' )
}
handle3 ( ) {
console. log ( '3' )
}
}
1.3.3 职责链模式
概念
一步操作可能分位多个职责角色来完成
把这些角色都分开,然后用一个链串起来
将发起者和各个处理者进行隔离
演示
class Action {
constructor ( name) {
this . name = name
this . nextAction = 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 ( )
JS 中的链式操作
职责链模式和业务结合较多,JS 中能联想到链式操作
jQuery 的链式操作 Promise.then 的链式操作
设计原则验证
1.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 中的应用
网页富文本编辑器操作,浏览器封装了一个命令对象
document.execCommand('bold')
document.execCommand('undo')
设计原则验证
1.3.5 备忘录模式
概念
随时记录一个对象的状态变化
随时可以恢复之前的某个状态(如撤销功能)
未找到 JS 中经典应用,除了一些工具(如编辑器)
演示
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 {
constuctor ( ) {
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 ( ) )
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 )
console. log ( a. number, b. number)
b. setNumber ( 100 )
console. log ( a. number, b. number)
1.3.7 访问者模式
1.3.8 解释器模式
概念
描述语言语法如何定义,如何解释和编译
用于专业场景