创建型模式(Creational Patterns)(5种)
1. 单例模式(Singleton) ***
- 作用: 确保一个类只有一个实例,并提供一个全局访问点
- 定义: 全局返回唯一实例
- 场景: 全局状态管理、日志器、数据库连接池
javascript
const Singleton = (() => {
let instance = null
function create() {
return {name: '单例模式'}
}
return {
getInstance() {
return instance || (instance = create())
}
}
})()
/*class Singleton {
constructor() {
if (!Singleton.instance) {
Singleton.instance = this;
}
return Singleton.instance;
}
someMethod() { console.log('Doing something'); }
}
const s1 = new Singleton();
const s2 = new Singleton();
console.log(s1 === s2);*/
2. 工厂方法模式(Factory Method) ***
- 作用: 定义创建对象的接口,由子类决定实例化哪个类
- 定义: 将对象创建延迟到子类
- 场景: 将对象的创建与使用分离,让系统在面对变化时能够更容易地扩展 (创建不同产品对象时,如 UI 组件库、文档生成器)
javascript
class Button {
render() { console.log('渲染按钮'); }
}
class ButtonFactory {
create() { return new Button(); }
}
const btnF = new ButtonFactory();
btnF.create().render()
3. 抽象工厂模式(Abstract Factory)
- 作用: 提供一个创建一系列相关对象的接口,无需指定它们的具体类
- 定义: 提供一个接口声明多个创建方法,具体工厂实现这些方法
- 场景: 用于跨平台UI组件库
javascript
class Button { render() {} }
class WindowsButton extends Button { render() { return 'Windows Button'; } }
class MacButton extends Button { render() { return 'Mac Button'; } }
class GUIFactory {
createButton() { throw new Error('Abstract method'); }
}
class WindowsFactory extends GUIFactory {
createButton() { return new WindowsButton(); }
}
class MacFactory extends GUIFactory {
createButton() { return new MacButton(); }
}
function app(factory) {
const btn = factory.createButton();
console.log(btn.render());
}
app(new WindowsFactory()); // Windows Button
app(new MacFactory()); // Mac Button
4. 建造者模式(Builder)
- 作用: 将复杂对象的构建过程拆分为多个步骤,允许逐步构建
- 定义: Director(指导者)控制构建流程,Builder提供逐步构建方法
- 场景: 构造具有多个可选参数的复杂对象(复杂UI,配置对象)
javascript
class Pizza {
constructor() {
this.size = null;
this.cheese = false;
}
}
class PizzaBuilder {
constructor() { this.pizza = new Pizza(); }
setSize(size) { this.pizza.size = size; return this; }
addCheese() { this.pizza.cheese = true; return this; }
build() { return this.pizza; }
}
const pizza = new PizzaBuilder()
.setSize('large')
.addCheese()
.build();
console.log(pizza)
5. 原型模式(Prototype)
- 作用: 通过复制现有实例来创建新对象,而非通过构造函数避免重复初始化
- 定义: 对象支持克隆(深拷贝或浅拷贝)
- 场景: 对象初始化成本高、需要大量相似对象时(如克隆配置)
javascript
const prototype = {
clone() {
return Object.create(this);
}
};
const obj1 = Object.create(prototype);
obj1.name = 'original';
const obj2 = obj1.clone();
console.log(obj2.name);
结构型模式(Structural Patterns)(7种)
6. 适配器模式(Adapter) ***
- 作用: 将一个类的接口转换成另一个类期望的接口, 使不兼容的接口可以工作
- 定义: 目标接口、适配者(Adaptee)、适配器(实现目标接口并持有适配者)
- 场景: 将不兼容的接口适配起来,集成第三方库或老代码,统一接口
javascript
// 旧接口
class OldPrinter {
print(text) { console.log(`打印: ${text}`); }
}
// 新接口期望的方法名
class NewPrinter {
printDocument(doc) { console.log(`打印文档: ${doc}`); }
}
// 适配器
class Adapter extends NewPrinter {
constructor(oldPrinter) {
super();
this.oldPrinter = oldPrinter;
}
printDocument(doc) {
this.oldPrinter.print(doc);
}
}
const old = new OldPrinter();
const adapted = new Adapter(old);
adapted.printDocument('hello'); // 打印: hello
7. 桥接模式(Bridge)
- 作用: 将抽象部分与实现部分分离,使它们可以独立变化
- 定义: 抽象类持有实现类接口,两者可独立扩展
- 场景: 跨平台图形绘制、不同颜色和形状的组合
javascript
// 实现(Implementation)
class DrawingAPI {
drawCircle(x, y, r) {}
}
class DrawingAPI1 extends DrawingAPI {
drawCircle(x, y, r) { return `API1: (${x},${y}) r=${r}`; }
}
class DrawingAPI2 extends DrawingAPI {
drawCircle(x, y, r) { return `API2: (${x},${y}) r=${r}`; }
}
// 抽象(Abstraction)
class Shape {
constructor(drawingAPI) { this.drawingAPI = drawingAPI; }
draw() {}
}
class Circle extends Shape {
constructor(x, y, r, drawingAPI) {
super(drawingAPI);
this.x = x; this.y = y; this.r = r;
}
draw() { return this.drawingAPI.drawCircle(this.x, this.y, this.r); }
}
const circle1 = new Circle(1,2,3, new DrawingAPI1());
console.log(circle1.draw()); // API1: (1,2) r=3
const circle2 = new Circle(4,5,6, new DrawingAPI2());
console.log(circle2.draw()); // API2: (4,5) r=6
8. 组合模式(Composite)
- 作用: 将对象组合成树形结构以表示"部分-整体"层次结构,使客户端统一对待单个对象和组合对象
- 定义: 组件接口(包含add、remove、getChild等方法),叶子和容器实现该接口
- 场景: 使用在 文件系统、UI组件树(如菜单、面板)、组织架构
javascript
class Component {
constructor(name) {this.name = name; }
display() { throw new Error('add display'); }
// add() {}
// remove() {}
}
class Leaf extends Component {
constructor(name) { super(name); }
display(depth) { console.log(`${'-'.repeat(depth)} ${this.name}`); }
}
class Composite extends Component {
constructor(name) { super(name); this.children = []; }
add(child) { this.children.push(child); }
remove(child) {
const index = this.children.indexOf(child)
if(index > -1) this.children.splice(index, 1);
}
display(depth = 0) {
console.log(`${'-'.repeat(depth)} ${this.name}`);
this.children.forEach(c => c.display(depth+2));
}
}
const root = new Composite('root');
const brach1 = new Composite('branch1');
brach1.add(new Leaf('left1-1'));
root.add(brach1);
root.add(new Leaf('left2'));
root.display();
9. 装饰器模式(Decorator) ***
- 作用: 动态地给对象添加额外职责,比继承更灵活
- 定义: 抽象组件、具体组件、抽象装饰(持有组件引用)、具体装饰
- 场景: 扩展对象功能而不修改原代码,用于日志/权限校验/缓存/中间件等场景
javascript
function calculate(a, b) {
return a + b;
}
function logDecorator(func) {
return function (...args) {
console.log(`[LOG] 调用函数: ${fn.name || 'anonymous'}, 参数:`, args);
const start = performance.now();
const res = func.call(this, ...args)
const end = performance.now();
console.log(`[LOG] 函数执行结果: ${result}, 耗时: ${(end - start).toFixed(2)}ms`);
return res;
}
}
const loggedCalculate = logDecorator(calculate)
loggedCalculate(3, 5)
10. 外观模式(Facade)
- 作用: 为子系统中的一组接口提供一个一致的界面,简化调用
- 定义: 外观类封装复杂子系统,提供简单方法
- 场景: 复杂系统封装(如启动/关闭流程)、简化复杂API调用、简化客户端调用
javascript
class CPU { start() { return 'CPU start'; } }
class Memory { load() { return 'Memory load'; } }
class HardDrive { read() { return 'HDD read'; } }
class ComputerFacade {
constructor() {
this.cpu = new CPU();
this.memory = new Memory();
this.hdd = new HardDrive();
}
start() {
return [this.cpu.start(), this.memory.load(), this.hdd.read()].join(', ');
}
}
const computer = new ComputerFacade();
console.log(computer.start()); // CPU start, Memory load, HDD read
11. 享元模式(Flyweight)
- 作用: 运用共享技术有效地支持大量细粒度的对象
- 定义: 内部状态(共享)和外部状态(不共享)分离,享元工厂管理共享对象
- 场景: 大量相似对象(如地图标记、文字字符)、对象池
javascript
class Character {
constructor(char) { this.char = char; } // 内部状态
display(fontSize) { console.log(`${this.char} with font ${fontSize}`); }
}
class CharacterFactory {
constructor() { this.characters = {}; }
getCharacter(char) {
if (!this.characters[char]) this.characters[char] = new Character(char);
return this.characters[char];
}
}
const factory = new CharacterFactory();
const c1 = factory.getCharacter('A');
c1.display(12); // A with font 12
const c2 = factory.getCharacter('A');
c2.display(14); // A with font 14
console.log(c1 === c2); // true
12. 代理模式(Proxy) ***
- 作用: 为其他对象提供一种代理以控制对这个对象的访问
- 定义: 代理对象与真实对象实现相同接口,代理持有真实对象引用,可添加额外操作(延迟加载、访问控制、日志等)
- 场景: 权限校验、日志记录、缓存、懒加载等场景
javascript
const target = {
name: 'secret',
getData() { return 'sensitive data'; }
};
const proxy = new Proxy(target, {
get(obj, prop) {
if (prop === 'getData') {
return () => '无权访问';
}
return obj[prop];
}
});
console.log(proxy.getData()); // 无权访问
// 代理 - 图片加载案例
class RealImage {
constructor(filename) {
this.filename = filename;
this.loadFromDisk();
}
loadFromDisk() { console.log(`Loading ${this.filename}`); }
display() { console.log(`Displaying ${this.filename}`); }
}
class ProxyImage {
constructor(filename) {
this.filename = filename;
this.realImage = null;
}
display() {
if (!this.realImage) this.realImage = new RealImage(this.filename);
this.realImage.display();
}
}
const image = new ProxyImage('photo.jpg');
image.display(); // Loading photo.jpg // Displaying photo.jpg // 加载并显示
image.display(); // Displaying photo.jpg // 只显示,不再加载
行为型模式(Behavioral Patterns)
13. 责任链模式(Chain of Responsibility)
- 作用: 使多个对象都有机会处理请求,避免请求发送者与接收者耦合
- 定义: 抽象处理者定义处理接口,具体处理者持有后继者引用,决定是否处理或传递
- 场景: 审批流程、事件冒泡、中间件管道
javascript
class Handler {
setNext(handler) { this.next = handler; return handler; }
handle(request) {
if (this.next) return this.next.handle(request);
return null;
}
}
class ConcreteHandlerA extends Handler {
handle(request) {
if (request === 'A') return 'Handled by A';
return super.handle(request);
}
}
class ConcreteHandlerB extends Handler {
handle(request) {
if (request === 'B') return 'Handled by B';
return super.handle(request);
}
}
class ConcreteHandlerC extends Handler {
handle(request) {
if (request === 'C') return 'Handled by C';
return super.handle(request);
}
}
const handlerA = new ConcreteHandlerA();
const handlerB = new ConcreteHandlerB();
const handlerC = new ConcreteHandlerC();
handlerA.setNext(handlerB).setNext(handlerC);
console.log(handlerA.handle('A')); // Handled by B
console.log(handlerA.handle('B')); // Handled by B
console.log(handlerA.handle('C')); // Handled by C
console.log(handlerA.handle('D')); // null
14. 命令模式(Command)
- 作用: 将请求封装为对象,从而可用不同的请求对客户进行参数化
- 定义: 命令接口(execute、undo),接收者(执行实际动作),调用者(invoker)触发命令
- 场景: 撤销/重做、任务队列、宏命令、事务操作
javascript
// 接受者
class Receiver {
action() { return 'Receiver action'; }
}
// 命令接口
class Command {
execute() {}
}
// 具体命令
class ConcreteCommand extends Command {
constructor(receiver) { super(); this.receiver = receiver; }
execute() { return this.receiver.action(); }
}
// 调用者
class Invoker {
setCommand(cmd) { this.command = cmd; }
executeCommand() { return this.command.execute(); }
}
const receiver = new Receiver();
const command = new ConcreteCommand(receiver);
const invoker = new Invoker();
invoker.setCommand(command);
console.log(invoker.executeCommand()); // Receiver action
15. 解释器模式(Interpreter)
- 作用: 给定一个语言,定义其文法表示,并定义一个解释器
- 定义: 抽象表达式(Abstract Expression),终结符表达式(TerminalExpression),非终结符表达式(NonterminalExpression),上下文(context)
- 场景: SQL解析、正则表达式、简单DSL(领域特定语言)
javascript
class Context { constructor(input) { this.input = input; } }
class Expression {
interpret(context) { return context.input; }
}
class TerminalExpression extends Expression {
interpret(context) { return context.input.toLowerCase(); }
}
class NonterminalExpression extends Expression {
constructor(expr) { super(); this.expr = expr; }
interpret(context) { return this.expr.interpret(context).toUpperCase(); }
}
const context = new Context('Hello');
const terminal = new TerminalExpression();
const nonterminal = new NonterminalExpression(terminal);
console.log(nonterminal.interpret(context)); // HELLO
16. 迭代器模式(Iterator)
- 作用: 提供一种方法顺序访问聚合对象中的各个元素,而不暴露其内部表示
- 定义: 迭代器接口(next、hasNext、current),聚合接口(createIterator)
- 场景: 集合遍历(JavaScript原生迭代器即为此模式)、统一不同数据结构遍历方式
javascript
class Iterator {
hasNext() {}
next() {}
}
class ConcreteIterator extends Iterator {
constructor(collection) {
super();
this.collection = collection;
this.index = 0;
}
hasNext() { return this.index < this.collection.length; }
next() { return this.collection[this.index++]; }
}
class Aggregate {
createIterator() {}
}
class ConcreteAggregate extends Aggregate {
constructor(items) { super(); this.items = items; }
createIterator() { return new ConcreteIterator(this.items); }
}
const aggregate = new ConcreteAggregate([1,2,3]);
const iterator = aggregate.createIterator();
while (iterator.hasNext()) {
console.log(iterator.next()); // 1,2,3
}
// ES6 迭代器模式
class MyCollection {
constructor(items) { this.items = items; }
[Symbol.iterator]() {
let index = 0;
const items = this.items;
return {
next() {
if (index < items.length) {
return { value: items[index++], done: false };
}
return { done: true };
}
};
}
}
const coll = new MyCollection([1,2,3]);
for (const val of coll) console.log(val); // 1 2 3
17. 中介者模式(Mediator)
- 作用: 提供一种方法顺序访问聚合对象中的各个元素,而不暴露其内部表示
- 定义: 中介者接口(通知方法),同事对象(Colleague)引用中介者
- 场景: 聊天室、组件间通信(如MVC中的Controller)、飞机管制系统
javascript
class Mediator {
notify(sender, event) {}
}
class ConcreteMediator extends Mediator {
constructor(colleagueA, colleagueB) {
super();
this.colleagueA = colleagueA;
this.colleagueB = colleagueB;
this.colleagueA.setMediator(this);
this.colleagueB.setMediator(this);
}
notify(sender, event) {
if (event === 'A') return this.colleagueB.receive();
if (event === 'B') return this.colleagueA.receive();
}
}
class Colleague {
setMediator(mediator) { this.mediator = mediator; }
send(event) { return this.mediator.notify(this, event); }
}
class ColleagueA extends Colleague {
receive() { return 'A received'; }
}
class ColleagueB extends Colleague {
receive() { return 'B received'; }
}
const a = new ColleagueA();
const b = new ColleagueB();
const mediator = new ConcreteMediator(a, b);
console.log(a.send('A')); // B received (间接)
18. 备忘录模式(Memento)
- 作用: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
- 定义: 发起人(Originator)创建备忘录,备忘录(Memento)存储状态,管理者(Caretaker)保存备忘录
- 场景: 撤销/重做、保存游戏进度、事务回滚
javascript
// 备忘录
class Memento {
constructor(state) { this.state = state; }
getState() { return this.state; }
}
// 发起人
class Originator {
setState(state) { this.state = state; }
getState() { return this.state; }
saveToMemento() { return new Memento(this.state); }
restoreFromMemento(memento) { this.state = memento.getState(); }
}
// 管理者 History
class Caretaker {
constructor() { this.mementos = []; }
addMemento(m) { this.mementos.push(m); }
getMemento(index) { return this.mementos[index]; }
}
const originator = new Originator();
const history = new Caretaker();
originator.setState('State1');
history.addMemento(originator.saveToMemento());
originator.setState('State2');
originator.restoreFromMemento(history.getMemento(0));
console.log(originator.getState()); // State1
19. 观察者模式(Observer)
- 作用: 定义对象间的一种一对多依赖关系,当一个对象状态改变时,所有依赖于它的对象都得到通知并被自动更新
- 定义: 被观察者(Subject 主题)维护观察者列表,提供注册、注销、通知方法;观察者(Observer)定义更新接口
- 场景: 用于解耦发布者和订阅者, 事件监听、响应式编程(Vue), 发布-订阅
javascript
// 被观察者:维护观察者列表,状态变化时通知所有观察者
class Subject {
constructor() {
this.observers = [];
}
attach(observer) {
this.observers.push(observer);
return this
}
notify(data) {
this.observers.forEach(obs => obs.update(data));
}
}
// 观察者:接收通知并执行更新
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(`${this.name} 收到更新: ${data}`)
}
}
const sub = new Subject();
const obs1 = new Observer('obs1');
const obs2 = new Observer('obs2');
sub.attach(obs1).attach(obs2);
sub.notify('hello'); // obs1 收到更新: hello obs2 收到更新: hello
20. 状态模式(State)
- 作用: 允许对象在内部状态改变时改变它的行为,好像修改了它的类 (避免了 if-else switch 的判断)
- 定义: 上下文(Context)持有当前状态对象,状态接口定义行为,具体状态实现特定行为
- 场景: 有限状态机(如订单状态、交通灯)、游戏角色状态
javascript
// 上下文
class Context {
constructor(state) { this.setState(state); }
setState(state) { this.state = state; this.state.setContext(this); }
request() { return this.state.handle(); }
}
// 状态抽象
class State {
setContext(context) { this.context = context; }
handle() {}
}
// 具体状态
class ConcreteStateA extends State {
handle() { return 'State A handling'; }
}
class ConcreteStateB extends State {
handle() { return 'State B handling'; }
}
const context = new Context(new ConcreteStateA());
console.log(context.request()); // State A handling
context.setState(new ConcreteStateB());
console.log(context.request()); // State B handling
// 字面量示例
// 状态对象
const states = {
A: {
handle(context) {
console.log('状态 A -> 切换到 B');
context.state = states.B;
}
},
B: {
handle(context) {
console.log('状态 B -> 切换到 A');
context.state = states.A;
}
}
};
// 上下文
const context = {
state: states.A,
request() {
this.state.handle(this);
}
};
context.request(); // 状态 A -> 切换到 B
context.request(); // 状态 B -> 切换到 A
21. 策略模式(Strategy)
- 作用: 定义一系列算法,把它们封装起来,并且使它们可以互相替换
- 定义: 1.定义策略接口(algorithm) 2.具体策略类 3.上下文(Context)类 4.创建上下文,根据需求选择策略 执行方法
- 场景: 表单验证算法、排序策略、支付方式(折扣计算)选择
javascript
class Context {
constructor(strategy) { this.strategy = strategy; }
setStrategy(strategy) { this.strategy = strategy; }
pay(amount) { return this.strategy.pay(amount); }
}
// class Strategy {
// pay(amount) { throw '请添加支付策略' }
// }
// class WechatPayStrategy extends Strategy {
class WechatPayStrategy {
pay(amount) {
console.log(`使用微信支付:${amount} 元`);
// 实际调用微信支付API...
return { success: true, method: 'wechat' };
}
}
class AlipayStrategy {
pay(amount) {
console.log(`使用支付宝支付:${amount} 元`);
return { success: true, method: 'alipay' };
}
}
// 使用示例
const payment = new Context(new WechatPayStrategy())
payment.executePayment(100); // 使用微信支付:100 元
// 切换为支付宝
payment.setStrategy(new AlipayStrategy());
payment.executePayment(100); // 使用支付宝支付:200 元
// 函数版
// 策略函数
const regularMember = price => price;
const goldMember = price => price * 0.9;
const diamondMember = price => price * 0.8;
// 上下文类
class PriceCalculator {
constructor(strategyFn) {
this.strategyFn = strategyFn;
}
setStrategy(strategyFn) {
this.strategyFn = strategyFn;
}
calculatePrice(originalPrice) {
return this.strategyFn(originalPrice);
}
}
// 使用方式与前面类似
const calculator = new PriceCalculator(regularMember);
console.log(calculator.calculatePrice(100)); // 100
calculator.setStrategy(goldMember);
console.log(calculator.calculatePrice(100)); // 90
22. 模板方法模式(Template Method)
- 作用: 定义一个操作中的算法骨架,而将一些步骤延迟到子类中
- 定义: 抽象类定义模板方法(final),并声明抽象步骤方法,子类实现抽象方法
- 场景: 框架基类(如React组件生命周期)、工作流引擎、钩子函数
javascript
class AbstractClass {
templateMethod() {
return `${this.step1()} ${this.step2()}`;
}
step1() { return 'Abstract step1'; }
step2() { return 'Abstract step2'; }
}
class ConcreteClass extends AbstractClass {
step2() { return 'Concrete step2'; }
}
const obj = new ConcreteClass();
console.log(obj.templateMethod()); // Abstract step1 Concrete step2
23. 访问者模式(Visitor)
- 作用: 表示一个作用于某对象结构中的各元素的操作,使可以在不改变各元素类的前提下定义作用于这些元素的新操作
- 定义: 访问者接口(visit方法对应每种元素),元素接口(accept访问者),具体元素实现accept,具体访问者实现操作
- 场景: 编译器语法树遍历(AST遍历)、报表生成、对象结构稳定但操作易变的场景
javascript
class Element {
accept(visitor) {}
}
class ConcreteElementA extends Element {
accept(visitor) { return visitor.visitConcreteElementA(this); }
operationA() { return 'ElementA'; }
}
class ConcreteElementB extends Element {
accept(visitor) { return visitor.visitConcreteElementB(this); }
operationB() { return 'ElementB'; }
}
class Visitor {
visitConcreteElementA(elem) {}
visitConcreteElementB(elem) {}
}
class ConcreteVisitor extends Visitor {
visitConcreteElementA(elem) { return `Visitor A ${elem.operationA()}`; }
visitConcreteElementB(elem) { return `Visitor B ${elem.operationB()}`; }
}
const elements = [new ConcreteElementA(), new ConcreteElementB()];
const visitor = new ConcreteVisitor();
elements.forEach(e => console.log(e.accept(visitor)));
// Visitor A ElementA
// Visitor B ElementB
结语
其实我们前端在开发中有涉及到相关的设计模式,只是没有去总结。