引言
设计模式的概念最早由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides(统称为“Gang of Four,GoF”)在 1994 年提出。他们在《Design Patterns: Elements of Reusable Object-Oriented Software》一书中总结了 23 种经典的软件设计模式,用于解决面向对象编程中的常见设计问题。
在前端开发中,虽然 JavaScript 具有动态和函数式特性,但这些设计模式仍然适用,能够帮助开发者提升代码的 可复用性、可维护性和可扩展性,尤其在大型项目、复杂组件体系或状态管理中尤为重要。
创建型模式(Creational Patterns)
创建型模式关注对象的创建方式,控制对象的实例化过程。
1. 单例模式(Singleton)
- 说明:保证一个类只有一个实例,并提供全局访问点。
- 前端示例:全局状态管理(Vuex、Redux Store)
class Store {
constructor() {
if (Store.instance) return Store.instance;
this.state = {};
Store.instance = this;
}
}
const store1 = new Store();
const store2 = new Store();
console.log(store1 === store2); // true
2. 工厂方法模式(Factory Method)
- 说明:定义一个创建对象的接口,由子类决定实例化哪一个类。
- 前端示例:根据不同环境创建 API 实例。
class Api {
constructor(baseURL) { this.baseURL = baseURL; }
}
class DevApi extends Api {}
class ProdApi extends Api {}
function createApi(env) {
if(env === 'dev') return new DevApi('http://localhost:3000');
return new ProdApi('https://api.example.com');
}
3. 抽象工厂模式(Abstract Factory)
- 说明:提供创建一系列相关或依赖对象的接口,而无需指定具体类。
- 前端示例:根据主题创建按钮和输入框。
class LightThemeFactory {
createButton() { return 'Light Button'; }
createInput() { return 'Light Input'; }
}
class DarkThemeFactory {
createButton() { return 'Dark Button'; }
createInput() { return 'Dark Input'; }
}
function renderUI(factory) {
console.log(factory.createButton(), factory.createInput());
}
renderUI(new DarkThemeFactory());
4. 建造者模式(Builder)
- 说明:将复杂对象的构建与表示分离,使同样的构建过程可以创建不同的表示。
- 前端示例:Modal 或表单组件构建器。
class ModalBuilder {
constructor() { this.modal = {}; }
setHeader(header) { this.modal.header = header; return this; }
setBody(body) { this.modal.body = body; return this; }
setFooter(footer) { this.modal.footer = footer; return this; }
build() { return this.modal; }
}
const modal = new ModalBuilder().setHeader('标题').setBody('内容').build();
5. 原型模式(Prototype)
- 说明:通过拷贝已有对象创建新对象,减少重复初始化开销。
- 前端示例:对象深拷贝、组件克隆。
const obj = { name: '张三', age: 18 };
const cloneObj = Object.assign({}, obj);
console.log(cloneObj);
二、结构型模式(Structural Patterns)
结构型模式关注对象之间的组合与结构关系。
6. 适配器模式(Adapter)
- 说明:将一个接口转换成客户端期望的接口。
- 前端示例:旧 API 兼容新接口。
class OldApi { getData() { return '旧接口数据'; } }
class ApiAdapter {
constructor(api) { this.api = api; }
fetch() { return this.api.getData(); }
}
const adapter = new ApiAdapter(new OldApi());
console.log(adapter.fetch());
7. 桥接模式(Bridge)
- 说明:将抽象与实现分离,使二者可以独立变化。
- 前端示例:组件渲染器抽象。
class Renderer { render(){} }
class WebRenderer extends Renderer { render() { console.log('Web Render'); } }
class MobileRenderer extends Renderer { render() { console.log('Mobile Render'); } }
class Component {
constructor(renderer) { this.renderer = renderer; }
display() { this.renderer.render(); }
}
new Component(new WebRenderer()).display();
8. 组合模式(Composite)
- 说明:将对象组合成树形结构,表示“部分-整体”的关系。
- 前端示例:组件树结构。
class Component { render(){} }
class Button extends Component { render(){ console.log('按钮'); } }
class Form extends Component {
constructor(){ super(); this.children=[]; }
add(c){ this.children.push(c); }
render(){ this.children.forEach(c => c.render()); }
}
9. 装饰器模式(Decorator)
- 说明:动态地给对象添加功能,而不修改其结构。
- 前端示例:高阶组件 HOC。
function log(target, key, desc) {
const old = desc.value;
desc.value = function(...args){ console.log(args); return old.apply(this,args); };
return desc;
}
class User {
@log sayHi(name){ return `Hi, ${name}`; }
}
10. 外观模式(Facade)
- 说明:为子系统提供统一接口,简化调用。
- 前端示例:封装复杂功能 API。
class Auth { login(){ console.log('login'); } }
class DB { save(){ console.log('save'); } }
class Facade {
constructor(){ this.auth = new Auth(); this.db = new DB(); }
doWork(){ this.auth.login(); this.db.save(); }
}
new Facade().doWork();
11. 享元模式(Flyweight)
- 说明:通过共享减少对象数量,提高性能。
- 前端示例:缓存复用组件实例。
const FlyweightFactory = (() => {
const pool = {};
return (key) => pool[key] ?? (pool[key] = {key});
})();
console.log(FlyweightFactory('btn') === FlyweightFactory('btn')); // true
12. 代理模式(Proxy)
- 说明:为对象提供一个代理以控制访问。
- 前端示例:Vue3 响应式 Proxy。
const data = { name: '小红' };
const proxy = new Proxy(data, {
get(target, prop){ console.log(prop); return target[prop]; },
set(target, prop, value){ console.log(prop, value); target[prop] = value; return true; }
});
proxy.name = '小明';
三、行为型模式(Behavioral Patterns)
行为型模式关注对象间的交互和职责分配。
13. 责任链模式(Chain of Responsibility)
- 说明:多个对象有机会处理请求,形成链式处理。
- 前端示例:中间件请求处理。
class Handler {
setNext(handler){ this.next = handler; return handler; }
handle(request){ this.next?.handle(request); }
}
14. 命令模式(Command)
- 说明:将请求封装为对象,可用于队列、日志、撤销。
- 前端示例:按钮点击命令。
class Command { execute(){} }
class AddCommand extends Command { execute(){ console.log('Add'); } }
const cmd = new AddCommand(); cmd.execute();
15. 解释器模式(Interpreter)
- 说明:定义语言语法,将句子解析为操作。
- 前端示例:模板解析。
const context = { a: 1, b: 2 };
function interpret(expr){ return eval(expr); }
console.log(interpret('a + b'));
16. 迭代器模式(Iterator)
- 说明:提供顺序访问集合元素的方式。
- 前端示例:数组、NodeList 遍历。
const arr = [1, 2, 3];
for(const item of arr){ console.log(item); }
17. 中介者模式(Mediator)
- 说明:通过中介对象封装对象间交互,降低耦合。
- 前端示例:事件总线。
class Mediator {
constructor(){ this.colleagues = []; }
register(c){ this.colleagues.push(c); }
notify(sender, msg){ this.colleagues.forEach(c => c !== sender && c.receive(msg)); }
}
18. 备忘录模式(Memento)
- 说明:在不暴露对象细节的情况下,保存和恢复对象状态。
- 前端示例:撤销/重做。
class Memento { constructor(state){ this.state = state; } }
class Originator {
setState(state){ this.state = state; }
save(){ return new Memento(this.state); }
restore(m){ this.state = m.state; }
}
19. 观察者模式(Observer)
- 说明:对象状态变化时通知所有观察者。
- 前端示例:Vue2 响应式系统。
class Subject {
constructor(){ this.observers = []; }
add(o){ this.observers.push(o); }
notify(data){ this.observers.forEach(o => o.update(data)); }
}
20. 状态模式(State)
- 说明:对象在内部状态改变时改变行为。
- 前端示例:按钮状态切换。
class Context {
constructor(state){ this.state = state; }
setState(state){ this.state = state; }
request(){ this.state.handle(); }
}
21. 策略模式(Strategy)
- 说明:封装算法,使其可互换。
- 前端示例:表单验证策略。
const strategies = { a: x => x * 2, b: x => x * 3 };
function calc(strategy, val){ return strategies[strategy](val); }
22. 模板方法模式(Template Method)
- 说明:定义算法骨架,子类实现具体步骤。
- 前端示例:组件生命周期模板。
class Game {
play(){ this.start(); this.end(); }
start(){};
end(){};
}
23. 访问者模式(Visitor)
- 说明:在对象结构上定义新的操作,而不改变对象结构。
- 前端示例:DOM 遍历操作。
class Visitor { visit(element){ console.log('访问', element); } }
这些模式在前端开发中广泛应用,帮助我们写出高可维护、可复用、可扩展的代码。