结构型模式
Adapter(适配器)
意图
将一个类的接口转换为用户希望的另外一个接口。
常用场景:封装有缺陷的接口设计、统一多个类的接口设计、兼容老版本接口、适配不同格式的数据等。
javascript
// 目标接口
const target = {
fn1() { },
fn2() { },
fn3() { },
}
// 需要适配的接口
const adaptee = {
fn1() { },
fnb() { },
fnc() { }
}
// 完成 fn2, fn3。实现后的 adeptor 具备 target 相关接口
const adeptor = {
...adaptee,
fn2() {
adaptee.fnb()
},
fn3() {
adaptee.fnc()
}
}
Bridge(桥接)
意图
将抽象部分与它的实现部分分离,使它们可以独立地变化。
核心思想:将一些通用方法提取出来,维护一个Implementor类,该类定义更细颗粒度的操作方法,而Abstraction则是基于这些操作方法的较高层次的操作。
Abstraction
定义抽象类的接口,维护一个指向Implementor
的指针
javascript
class Window {
constructor() { }
drawText() {}
drawRect() {}
}
RefinedAbstraction
扩充由Abstraction
定义的接口
javascript
class IconWindow extends Window {
drawBorder() {
this.drawText()
this.drawRect()
}
}
Implementor
定义实现的类的接口,该接口不一定要与Abstraction
接口完全一致。一般来讲,Implementor
接口仅提供基本操作,而Abstraction
则定义了基于这些基本操作对的较高层次的操作。
javascript
class WindowImp {
drawLine() { }
}
ConcreteImplementor
实现Implementor
接口
javascript
class XWindowImp extends WindowImp {
drawLine() {
// 画 window 上的线条
}
}
class MacWindowImp extends WindowImp {
drawLine() {
// 画 Mac 上的线条
}
}
Composite(组合)
意图
将对象组合成树形接口以表示“部分 - 整体”的层次结构。Composite
使得用户对单个对象和组合对象的使用具有一致性。
如创建节点时,分为很多种情况。遇到数组时(Composite
),又会递归去创建节点。
javascript
function createElement(node) {
if (Array.isArray(node)) {
node.forEach((child) => {
createElement(child)
})
} else if (node.type === 'text') {
createText()
} else {
createNode()
}
}
Decorator(装饰)
意图
动态地给一个对象添加一些额外职责。就增加功能来讲,Decorator模式相比于生成子类更加灵活。
javascript
function border(fn) {
console.log('add border')
return (...args) => {
fn(...args)
}
}
function shape(color) {
console.log('shape:', color)
}
border(shape)('red')
Facade(外观)
意图
为子系统中的一组接口提供一个一致的界面,Facade 定义了一个高层接口,这个接口使得这一系统更容易使用
侧重于通过颗粒比较小的接口合成一个高层的接口,使得外部更容易调用。
javascript
const systemA = {
fn1() { },
fn2() { },
fn3() { }
}
const systemB = {
fn1() { },
fn2() { },
fn3() { }
}
// 高层接口
const facadeMethod = () => {
systemA.fn1()
systemB.fn2()
systemB.fn3()
systemA.fn3()
}
Flyweight(享元)
意图
运用共享技术有效地支持大量细粒度的对象。
进行划分细颗粒度的对象,使得这些对象能够共享,达到减少内存占用的目的。
Proxy(代理)
意图
为其他对象提供一种代理以控制这个对象的访问。
javascript
const user = {
name: '模式'
}
const validate = () => {
console.log('校验 user')
}
const proxyUser = new Proxy(user, {
get(target, propKey) {
validate()
return `代理_${target[propKey]}`
}
})
console.log('proxyUser.name ==> ', proxyUser.name);
// 校验 user
// proxyUser.name ==> 代理_模式