一、创建型
1、工厂模式
提供一个创建对象的接口,但由子类决定实例化哪个类。用工厂方法代替new操作,根据传入的类型参数动态创建不同的对象实例。
如:简单工厂模式
// 产品接口
class Product {
use() {}
}
// 具体产品A
class ConcreteProductA extends Product {
use() {
console.log('Using ConcreteProductA');
}
}
// 具体产品B
class ConcreteProductB extends Product {
use() {
console.log('Using ConcreteProductB');
}
}
// 工厂函数
function SimpleFactory(type) {
switch (type) {
case 'A':
return new ConcreteProductA();
case 'B':
return new ConcreteProductB();
default:
throw new Error('Unknown product type');
}
}
// 客户端代码
const productA = SimpleFactory('A');
productA.use(); // 输出: Using ConcreteProductA
const productB = SimpleFactory('B');
productB.use(); // 输出: Using ConcreteProductB
2、单例模式
一个类只有一个实例,只有一个访问入口。
如:vuex 和 redux中的store
常用的模块单例模式如下:
// singleton.js
class Singleton {
constructor() {
if (!Singleton.instance) {
Singleton.instance = this;
}
return Singleton.instance;
}
someMethod() {
console.log('Hello World');
}
}
const instance = new Singleton();
Object.freeze(instance); // 冻结对象,防止修改
export default instance;
// main.js
import singleton from './singleton.js';
singleton.someMethod(); // 输出: Hello World
3、原型模式(prototype)
创建一个新对象,新对象继承原对象的属性和方法。
如:prototype、Object.Create方法创建函数、ES6中class的extends
二、结构型
1、适配器模式
解决类之间接口不兼容问题,通过适配器模式,由一个对象对另一个对象进行封装。
如:整合第三方SDK、封装旧接口、vue的computed
2、代理模式
当请求到达实际的原始对象之前或者之后执行的某种操作。
如:ES6 的 proxy、jQuery.proxy()方法
3、装饰者模式
动态地给某个对象添加一些额外的职责,是一种实现继承的替代方案。
如:ES7 Decorator、core-decorators
对比:
适配器模式: 提供一个不同的接口(如不同版本的插头)
代理模式: 提供一模一样的接口;显示原有功能,但是经过限制之后的
装饰者模式: 扩展功能,原有功能不变且可直接使用
三、行为型
1、迭代器模式
可以遍历数据结构的方法
如:Array.prototype.forEach、jQuery中的$.each()、ES6 Iterator
2、策略模式
定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。
适用于有多种算法可以实现同一功能的场景,且这些算法可以互换使用。如:在电商平台中,可以根据不同的促销策略选择不同的折扣计算方式。
3、观察者模式(发布-订阅模式)
在给定对象上定义一个事件侦听器,当该对象执行我们侦听的操作时,执行一些事件。
如原生JS的DOM事件监听,React的useEffect钩子
4、命令模式
将请求或操作封装到一个对象中,从而允许你将请求或操作的发起者与具体执行者解耦。
多个事件请求可以访问一个封装的对象,通过传参不同执行不同的操作。
// 文本编辑器类,作为接收者
class TextEditor {
constructor() {
this.text = '';
this.history = [];
}
insertText(text) {
this.history.push(this.text);
this.text += text;
console.log(`Inserted: ${text}`);
}
deleteText(length) {
this.history.push(this.text);
this.text = this.text.substring(0, this.text.length - length);
console.log(`Deleted last ${length} characters`);
}
undo() {
if (this.history.length > 0) {
this.text = this.history.pop();
console.log('Undo operation');
} else {
console.log('No more actions to undo');
}
}
getText() {
return this.text;
}
}
// 命令接口
class Command {
execute() {}
undo() {}
}
// 插入文本命令实现
class InsertTextCommand extends Command {
constructor(editor, text) {
super();
this.editor = editor;
this.text = text;
}
execute() {
this.editor.insertText(this.text);
}
undo() {
this.editor.undo();
}
}
// 删除文本命令实现
class DeleteTextCommand extends Command {
constructor(editor, length) {
super();
this.editor = editor;
this.length = length;
}
execute() {
this.editor.deleteText(this.length);
}
undo() {
this.editor.undo();
}
}
// 客户端代码
const editor = new TextEditor();
const insertCommand = new InsertTextCommand(editor, 'Hello, World!');
const deleteCommand = new DeleteTextCommand(editor, 6);
// 执行命令
insertCommand.execute(); // 输出: Inserted: Hello, World!
deleteCommand.execute(); // 输出: Deleted last 6 characters
// 撤销操作
deleteCommand.undo(); // 输出: Undo operation
insertCommand.undo(); // 输出: Undo operation
5、状态模式
允许对象在其内部状态发生改变时改变其行为,将状态转换的代码从主要业务逻辑中抽离出来。
如:阅读状态的改变
// 状态接口
class State {
handle(context) {}
}
// 具体状态:未读状态
class UnreadState extends State {
handle(context) {
console.log('Text is unread');
context.setState(new ReadState());
}
}
// 具体状态:已读状态
class ReadState extends State {
handle(context) {
console.log('Text is read');
context.setState(new UnreadState());
}
}
// 上下文类
class TextEditor {
constructor() {
this.state = new UnreadState(); // 初始状态为未读
}
setState(state) {
this.state = state;
}
toggleReadStatus() {
this.state.handle(this);
}
}
// 客户端代码
const editor = new TextEditor();
editor.toggleReadStatus(); // 输出: Text is unread
editor.toggleReadStatus(); // 输出: Text is read
editor.toggleReadStatus(); // 输出: Text is unread