Skip to content

设计模式

设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。

分类

图源:设计模式目录:22种设计模式

创建型设计模式

单例模式

一个类只允许创建一个实例。

典型:Vuex 的单一状态树 State | Vuex

Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。

工厂模式

核心:解耦对象的创建与使用

把不同的对象的创建过程封装起来,通过统一的接口,根据输入(比如字符串、配置等)来创建不同的实例。

比如 document.createElement('div'),我们不需要知道一个 div 元素节点到底是如何创建的,是不是需要什么参数。

工厂方法、工厂类... 都是工厂模式的表现形式之一

建造者模式

核心: 将一个复杂对象的构建与表示分离

在创建对象时,考虑必要参数、可选参数,专门有个 builder 类/函数来负责二次封装对象的复杂创建过程。

原型模式

如果对象的创建成本大,或想要复用已有对象的功能,可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。

JS 的原型链就是这种模式,构造函数有 prototype,对象有 consturctor 和 __proto__

未完待续....

结构型设计模式

代理模式

为对象做代理,在外界访问、操作对象时,先经由代理层操作,这个代理层可以做的事情就多了,比如以下场景:

  • 对象访问和操作代理:vue 基于代理模式实现了数据劫持和视图更新派发
  • 行为代理: 创建一个 PImage,内部代理一个真实的image元素节点,在调用 setSrc 方法时,首先会加载占位图或缩略图,load 后再替换为真实图片
  • 缓存代理:为函数的结果进行代理,闭包缓存

装饰器模式

es6 中的装饰器

js
@testable
class MyTestableClass {
  // ...
}
function testable(target) {
  target.isTestable = true;
}
MyTestableClass.isTestable // true

// 等同于
@decorator
class A {}

class A {}
A = decorator(A) || A;

react 和 redux 貌似常常使用,connect 函数用于将 React 组件与 Redux 的 store 连接起来,使其能够读取状态(mapStateToProps)和派发动作(mapDispatchToProps),可以抽取为装饰器,并用 @语法糖优化。

或者用现在推荐的钩子 useSelector / useDispatch

适配器模式

将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。