1.什么是设计模式?
设计模式是一种解决特定场景下重复出现问题的经验总结,是对代码重构的一种指导,旨在提高代码的可读性、可复用性、可靠性和可维护性。设计模式是在代码结构层次上的解决方案,描述了类或对象之间的交互关系。设计模式不是一种代码的趋势或标准,而是一种解决问题的思路。
2.为什么需要使用设计模式?
设计模式为代码的性能和重用性提供了基础,通过代码的复用和抽象,遵循设计原则和规范,提高代码的可读性、可维护性、可扩展性和可重用性。设计模式能够让我们在代码实现中减少重复性的设计工作,使得代码更加简洁易懂,更加符合面向对象设计的思想。
3.23种常用的设计模式简介
创建型模式
1.工厂模式
工厂模式是一种工程模式,用于创建对象。一个工厂类封装了对象创建的过程,调用者只需要传递参数,就可以获取到想要的对象,而无需了解对象的创建细节。
class Product { constructor(name) { this.name = name; } } class Creator { create(name) { return new Product(name); } } const creator = new Creator(); const product1 = creator.create('Product 1'); console.log('product1:', product1);
2.抽象工厂模式
抽象工厂模式是一种工厂模式的扩展应用,一个抽象工厂通过一组有关联的工厂方法来创建一组相关或者依赖对象。
class ProductA { constructor(name) { this.name = name; } } class ProductB { constructor(name) { this.name = name; } } class AbstractFactory { createProductA() {} createProductB() {} } class ConcreteFactory1 extends AbstractFactory { createProductA() { return new ProductA('ConcreteFactory1 - ProductA'); } createProductB() { return new ProductB('ConcreteFactory1 - ProductB'); } } class ConcreteFactory2 extends AbstractFactory { createProductA() { return new ProductA('ConcreteFactory2 - ProductA'); } createProductB() { return new ProductB('ConcreteFactory2 - ProductB'); } } const factory1 = new ConcreteFactory1(); console.log('productA:', factory1.createProductA()); console.log('productB:', factory1.createProductB()); const factory2 = new ConcreteFactory2(); console.log('productA:', factory2.createProductA()); console.log('productB:', factory2.createProductB());
3.单例模式
单例模式是限制类只能实例化一次的一种模式。单例模式在 JavaScript 中比较常用,尤其是在全局状态管理中。
class Singleton { static instance = null; static getInstance() { if (Singleton.instance === null) { Singleton.instance = new Singleton(); } return Singleton.instance; } constructor() { if (Singleton.instance !== null) { throw new Error('该类只能实例化一次'); } this.name = 'Singleton'; } } const instance1 = Singleton.getInstance(); console.log('instance1:', instance1); const instance2 = Singleton.getInstance(); console.log('instance2:', instance2); console.log('instance1 === instance2:', instance1 === instance2)
4.原型模式
原型模式基于已有的对象,通过克隆的方式得到一个新的对象。在 JavaScript 中,对象的复制可以直接使用 Object.create
实现。
const person = { name: 'John', age: 20 }; const clonePerson = Object.create(person); console.log('clonePerson:', clonePerson); console.log('clonePerson.name:', clonePerson.name); console.log('clonePerson.age:', clonePerson.age);
5.建造者模式
建造者模式适用于创建一种复杂对象,对象的创建过程较为复杂,需要经过多个步骤或者需要参数组合。通过建造者模式可以将对象的构建过程和表示分离开来,使得同样的构建过程可以创建出不同的表示。
class Product { constructor(builder) { this.name = builder.name; this.price = builder.price; this.color = builder.color; this.size = builder.size; } } class ProductBuilder { constructor() { this.name = ''; this.price = 0; this.color = ''; this.size = ''; } setName(name) { this.name = name; return this; } setPrice(price) { this.price = price; return this; } setColor(color) { this.color = color; return this; } setSize(size) { this.size = size; return this; } build() { return new Product(this); } } const product = new ProductBuilder() .setName('Product') .setPrice(100) .setColor('blue') .setSize('big') .build(); console.log(product);
结构型模式
1.适配器模式
适配器模式用于解决两个接口不兼容的问题,它将一个类的接口转换成客户期待的另一个接口,以满足客户的需求。
class Target { request() { return 'Target'; } } class Adaptee { specificRequest() { return 'Adaptee'; } } class Adapter extends Target { constructor(adaptee) { super(); this.adaptee = adaptee; } request() { return this.adaptee.specificRequest(); } } const target = new Target(); console.log('target.request():', target.request()); const adaptee = new Adaptee(); console.log('adaptee.specificRequest():', adaptee.specificRequest()); const adapter = new Adapter(adaptee); console.log('adapter.request():', adapter.request());
2.桥接模式
桥接模式通过将实现部分和抽象部分分离,使它们可以独立地变化。桥接模式的思想是,将抽象与实现分离开来,使它们可以独立变化,在两者之间搭建起桥梁,从而实现灵活的组合。
class Implementor { operationImpl() {} } class ConcreteImplementorA extends Implementor { operationImpl() { return 'ConcreteImplementorA' } } class ConcreteImplementorB extends Implementor { operationImpl() { return 'ConcreteImplementorB' } } class Abstraction { constructor(implementor) { this.implementor = implementor; } operation() {} } class RefinedAbstraction extends Abstraction { operation() { return this.implementor.operationImpl(); } } const implementorA = new ConcreteImplementorA(); const refinedAbstraction1 = new RefinedAbstraction(implementorA); console.log('refinedAbstraction1.operation():', refinedAbstraction1.operation()); const implementorB = new ConcreteImplementorB(); const refinedAbstraction2 = new RefinedAbstraction(implementorB); console.log('refinedAbstraction2.operation():', refinedAbstraction2.operation());
3.组合模式
组合模式将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端可以像使用单个对象一样来处理复杂的层次结构对象。在组合模式中,叶子节点和组合节点均实现相同的接口,使得客户端无需区分叶子节点和组合节点,就可以对整个树进行递归遍历,并执行相应的操作。
class Component { add(component) {} remove(component) {} getChild(index) {} operation(){} } class Composite extends Component { constructor(name) { super(); this.name = name; this.children = []; } add(component) { this.children.push(component); } remove(component) { const index = this.children.indexOf(component); if (index > -1) { this.children.splice(index, 1); } } getChild(index) { return this.children[index]; } operation() { console.log(`Composite ${this.name} operation`); this.children.forEach((child) => { child.operation(); }); } } class Leaf extends Component { constructor(name) { super(); this.name = name; } operation() { console.log(`Leaf ${this.name} operation`); } } const root = new Composite('root'); const branch1 = new Composite('branch1'); const leaf1 = new Leaf('leaf1'); const leaf2 = new Leaf('leaf2'); branch1.add(leaf1); branch1.add(leaf2); const branch2 = new Composite('branch2'); const leaf3 = new Leaf('leaf3'); branch2.add(leaf3); root.add(branch1); root.add(branch2); console.log('root.operation():'); root.operation();
4.装饰者模式
装饰者模式在不改变原有对象的基础上,通过对其实例进行包装或者继承的方式,动态的为其增加新的行为。
class Component { operation() {} } class ConcreteComponent extends Component { operation() { console.log('ConcreteComponent operation'); } } class Decorator extends Component { constructor(component) { super(); this.component = component; } operation() { this.component.operation(); } } class ConcreteDecoratorA extends Decorator { constructor(component) { super(component); this.addedBehavior = 'ConcreteDecoratorA'; } operation() { super.operation(); console.log(`ConcreteDecoratorA operation ${this.addedBehavior}`); } } class ConcreteDecoratorB extends Decorator { constructor(component) { super(component); this.addedBehavior = 'ConcreteDecoratorB'; } operation() { super.operation(); console.log(`ConcreteDecoratorB operation ${this.addedBehavior}`); } } const component = new ConcreteComponent(); const decoratorA = new ConcreteDecoratorA(component); console.log('decoratorA.operation():'); decoratorA.operation(); const decoratorB = new ConcreteDecoratorB(component); console.log('decoratorB.operation():'); decoratorB.operation();
5.外观模式
外观模式为子系统提供一个统一的接口,以定义一组高层接口,从而简化子系统的使用。在外观模式中,客户端通过外观类来间接调用子系统的内部功能接口。
class SubsystemA { operationA() { console.log('SubsystemA operationA'); } } class SubsystemB { operationB() { console.log('SubsystemB operationB'); } } class Facade { constructor() { this.subsystemA = new SubsystemA(); this.subsystemB = new SubsystemB(); } operation() { this.subsystemA.operationA(); this.subsystemB.operationB(); } } const facade = new Facade(); console.log('facade.operation():'); facade.operation();
6.享元模式
享元模式是一种对象池的思想,将需要多次重复创建的对象缓存起来,当需要使用时直接从对象池中取出。享元模式可以有效减少对象的创建和销毁次数,从而提高性能。
class FlyweightFactory { constructor() { this.flyweights = new Map(); } getFlyweight(key) { if (!this.flyweights.has(key)) { this.flyweights.set(key, new ConcreteFlyweight(key)); } return this.flyweights.get(key); } } class Flyweight { operation() {} } class ConcreteFlyweight extends Flyweight { constructor(key) { super(); this.key = key; } operation() { console.log(`ConcreteFlyweight(${this.key}) operation`); } } const factory = new FlyweightFactory(); const flyweight1 = factory.getFlyweight('key1'); const flyweight2 = factory.getFlyweight('key2'); const flyweight3 = factory.getFlyweight('key1'); console.log('flyweight1 ===flyweight2:', flyweight1 === flyweight2); console.log('flyweight1 === flyweight3:', flyweight1 === flyweight3);
7.代理模式
代理模式为其他对象提供一种代理以控制对这个对象的访问。在代理模式中,代理类与被代理类实现相同的接口,客户端调用代理类的方法,代理类再进行相应的处理。
class Subject { request() {} } class RealSubject extends Subject { request() { console.log('RealSubject request'); } } class Proxy extends Subject { constructor(realSubject) { super(); this.realSubject = realSubject; } request() { if (this.checkAccess()) { this.realSubject.request(); this.logAccess(); } } checkAccess() { console.log('Proxy checkAccess'); return true; } logAccess() { console.log('Proxy logAccess'); } } const realSubject = new RealSubject(); const proxy = new Proxy(realSubject); proxy.request();
行为型模式
行为型模式关注类和对象之间的通信,确保能够在系统中各个对象之间以及处理链中进行有效的通信。
1. 职责链模式
职责链模式是一种使得一个请求可以被多个对象处理的模式。通过这种方式可以实现请求的发送者和接收者之间的解耦,实现代码的复用和扩展性的提高。
// Handler class Handler { constructor() { this.nextHandler = null; } setNextHandler(handler) { this.nextHandler = handler; } handleRequest(request) { if (this.nextHandler != null) { this.nextHandler.handleRequest(request); } } } // ConcreteHandler1 class ConcreteHandler1 extends Handler { handleRequest(request) { if (request.condition) { // do something } else { super.handleRequest(request); } } } // ConcreteHandler2 class ConcreteHandler2 extends Handler { handleRequest(request) { if (request.condition) { // do something } else { super.handleRequest(request); } } } // Client var h1 = new ConcreteHandler1(); var h2 = new ConcreteHandler2(); h1.setNextHandler(h2); h1.handleRequest(request);
2. 命令模式
命令模式把请求封装成对象,从而使你可以使用不同的请求、队列或者日志来支持请求的可撤销操作,也能够支持请求的排队或者记录日志等操作。
// Receiver class Receiver { action1() { console.log('Action1 is called.'); } action2() { console.log('Action2 is called.'); } } // Command class Command { constructor(receiver) { this.receiver = receiver; } execute() {} } // ConcreteCommand1 class ConcreteCommand1 extends Command { execute() { this.receiver.action1(); } } // ConcreteCommand2 class ConcreteCommand2 extends Command { execute() { this.receiver.action2(); } } // Invoker class Invoker { constructor() { this.commands = []; } addCommand(command) { this.commands.push(command); } executeCommands() { for (let command of this.commands) { command.execute(); } } } // Client var receiver = new Receiver(); var command1 = new ConcreteCommand1(receiver); var command2 = new ConcreteCommand2(receiver); var invoker = new Invoker(); invoker.addCommand(command1); invoker.addCommand(command2); invoker.executeCommands();
3. 解释器模式
解释器模式是一种能够将语言元素分离的模式,对于复杂的语言解析器,可以将其拆分为简单的语言元素,再通过解释器进行解析。
// Context class Context { constructor(input) { this.input = input; this.output = null; } getInput() { return this.input; } setInput(input) { this.input = input; } getOutput() { return this.output; } setOutput(output) { this.output = output; } } // AbstractExpression class AbstractExpression { interpret(context) {} } // TerminalExpression class TerminalExpression extends AbstractExpression { interpret(context) { let input = context.getInput(); context.setOutput(input); } } // NonterminalExpression class NonterminalExpression extends AbstractExpression { interpret(context) { let input = context.getInput(); // do something context.setOutput(output); } } // Client var context = new Context(input); let list = []; list.push(new TerminalExpression()); list.push(new NonterminalExpression()); for (let exp of list) { exp.interpret(context); } console.log(context.getOutput());
4. 迭代器模式
迭代器模式提供一种访问集合对象的方法,不需要暴露对象内部的元素,提供了更好的遍历集合元素的方法。
// Aggregate class Aggregate { constructor() {} createIterator() {} } // ConcreteAggregate class ConcreteAggregate extends Aggregate { constructor() { super(); this.collection = []; } addItem(item) { this.collection.push(item); } getItem(index) { return this.collection[index]; } getLength() { return this.collection.length; } createIterator() { return new ConcreteIterator(this); } } // Iterator class Iterator { constructor(aggregate) {} first() {} next() {} isDone() {} currentItem() {} } // ConcreteIterator class ConcreteIterator extends Iterator { constructor(aggregate) { super(); this.aggregate = aggregate; this.index = 0; } first() { this.index = 0; } next() { if (this.index < this.aggregate.getLength()) { this.index++; } } isDone() { return this.index === this.aggregate.getLength(); } currentItem() { return this.aggregate.getItem(this.index); } } // Client var collection = new ConcreteAggregate(); collection.addItem('apple'); collection.addItem('orange'); collection.addItem('banana'); let iterator = collection.createIterator(); while (!iterator.isDone()) { console.log(iterator.currentItem()); iterator.next(); }
5. 中介者模式
中介者模式定义一个中介者对象来封装一系列的对象交互,使得各个对象之间的关系变得更加松散。中介者模式可以降低对象之间的耦合度,提高系统的灵活性。
// Mediator class Mediator { constructor() {} ColleagueChanged() {} } // ConcreteMediator class ConcreteMediator extends Mediator { constructor() { super(); this.colleague1 = null; this.colleague2 = null; } setcolleague1(colleague1) { this.colleague1 = colleague1; } setcolleague2(colleague2) { this.colleague2 = colleague2; } ColleagueChanged() { this.colleague1.action(); this.colleague2.action(); } } // Colleague class Colleague { constructor(mediator) { this.mediator = mediator; } change() { this.mediator.ColleagueChanged(); } } // ConcreteColleague1 class ConcreteColleague1 extends Colleague { constructor(mediator) { super(mediator); } action() { console.log('ConcreteColleague1 has received the message!'); } } // ConcreteColleague2 class ConcreteColleague2 extends Colleague { constructor(mediator) { super(mediator); } action() { console.log('ConcreteColleague2 has received the message!'); } } // Client var mediator = new ConcreteMediator(); var colleague1 = new ConcreteColleague1(mediator); var colleague2 = new ConcreteColleague2(mediator); mediator.setcolleague1(colleague1); mediator.setcolleague2(colleague2); colleague1.change();
6. 备忘录模式
备忘录模式是一种捕获当前对象的状态,并能够在需要时恢复其状态的机制,它使得保存和恢复可以无缝进行,不影响系统的依赖性。
// Originator class Originator { constructor() { this.state = ''; } setState(state) { this.state = state; } getState() { return this.state; } saveStateMemento() { return new Memento(this.state); } getStateFromMemento(memento) { this.state = memento.getState(); } } // Memento class Memento { constructor(state) { this.state = state; } getState() { return this.state; } } // Caretaker class Caretaker { constructor() { this.mementoList = []; } add(memento) { this.mementoList.push(memento); } get(index) { return this.mementoList[index]; } } // Client var orig = new Originator(); var care = new Caretaker(); orig.setState('State1'); orig.setState('State2'); care.add(orig.saveStateMemento()); orig.setState('State3'); care.add(orig.saveStateMemento()); orig.setState('State4'); console.log("Current State: " + orig.getState()); orig.getStateFromMemento(care.get(1)); console.log("Second saved State: " + orig.getState());
7. 观察者模式
观察者模式是一种对象间的一对多关系,当某个对象发生改变时,所有依赖于它的对象都能得到通知。它可以使得各个对象之间的关系更加简单、可复用和扩展性强。
// Subject class Subject { constructor() { this.observers = []; } registerObserver(observer) { this.observers.push(observer); } removeObserver(observer) { let index = this.observers.indexOf(observer); if (index > -1) { this.observers.splice(index, 1); } } notifyObservers() { for (let observer of this.observers) { observer.update(); } } } // ConcreteSubject class ConcreteSubject extends Subject { constructor() { super(); this.state = ''; } getState() { return this.state; } setState(state) { this.state = state; this.notifyObservers(); } } // Observer class Observer { constructor() {} update() {} } // ConcreteObserver1 class ConcreteObserver1 extends Observer { constructor(subject) { super(); this.subject = subject; this.subject.registerObserver(this); } update() { console.log('ConcreteObserver1 state is changed!'); } } // ConcreteObserver2 class ConcreteObserver2 extends Observer { constructor(subject) { super(); this.subject = subject; this.subject.registerObserver(this); } update() { console.log('ConcreteObserver2 state is changed!'); } } // Client var subject = new ConcreteSubject(); var observer1 = new ConcreteObserver1(subject); var observer2 = new ConcreteObserver2(subject); subject.setState('State1');
8. 状态模式
状态模式是一种允许对象在其内部状态改变时更改其行为的模式。通常,它会把对象的状态和行为分离,使得在每种状态下它们都可以独立变化,从而可以更好的管理状态之间的转换。
// State class State { constructor() {} handle(context) {} } // ConcreteState1 class ConcreteState1 extends State { constructor() { super(); } handle(context) { console.log('ConcreteState1 state is handled.'); context.setState(new ConcreteState2()); } } // ConcreteState2 class ConcreteState2 extends State { constructor() { super(); } handle(context) { console.log('ConcreteState2 state is handled.'); context.setState(new ConcreteState1()); } } // Context class Context { constructor() { this.state = new ConcreteState1(); } getState() { return this.state; } setState(state) { this.state = state; } request() { this.state.handle(this); } } // Client var ctx = new Context(); ctx.request(); ctx.request();
9. 策略模式
策略模式允许在运行时选择使用哪个算法库和子系统,从而可以在不修改代码的情况下更改系统的行为。它将算法的实现封装成策略类,使得客户端可以独立于具体的算法。
// Context class Context { constructor(strategy) { this.strategy = strategy; } getStrategy() { return this.strategy; } setStrategy(strategy) { this.strategy = strategy; } executeStrategy() { return this.strategy.execute(); } } // Strategy class Strategy { constructor() {} execute() {} } // ConcreteStrategy1 class ConcreteStrategy1 extends Strategy { constructor() { super(); } execute() { console.log('ConcreteStrategy1 is executed.'); } } // ConcreteStrategy2 class ConcreteStrategy2 extends Strategy { constructor() { super(); } execute() { console.log('ConcreteStrategy2 is executed.'); } } // Client var strategy1 = new ConcreteStrategy1(); var strategy2 = new ConcreteStrategy2(); var context = new Context(strategy1); context.executeStrategy(); context.setStrategy(strategy2); context.executeStrategy();
10. 模板方法模式
模板方法模式定义算法骨架,而将算法中的某些步骤延迟到子类中。模板方法让子类能够不改变算法的结构,而重新定义算法的某些步骤。
// AbstractClass class AbstractClass { constructor() {} operation() { console.log('Step 1.'); this.step1(); console.log('Step 2.'); this.step2(); } step1() {} step2() {} } // ConcreteClass1 class ConcreteClass1 extends AbstractClass { constructor() { super(); } step1() { console.log('ConcreteClass1 Step1 is executed.'); } step2() { console.log('ConcreteClass1 Step2 is executed.'); } } // ConcreteClass2 class ConcreteClass2 extends AbstractClass { constructor() { super(); } step1() { console.log('ConcreteClass2 Step1 is executed.'); } step2() { console.log('ConcreteClass2 Step2 is executed.'); } } // Client var c1 = new ConcreteClass1(); c1.operation(); var c2 = new ConcreteClass2(); c2.operation();
设计模式的优缺点
优点:
- 容易维护、易于扩展和修改;
- 提高代码的可复用性、灵活性和可维护性;
- 提供了解决通用问题的方案,使得代码更加规范;
- 使系统更加灵活,能够适应变化的需求。
缺点:
- 增加代码的复杂性,不利于代码阅读和理解;
- 设计模式需要额外的学习和实践成本;
- 设计模式不一定适用于所有的场景。
实际应用
设计模式广泛应用于软件工程中,特别是在软件架构和框架中。例如,在Web应用程序中,Model-View-Controller (MVC) 模式被用于将视图、控制器和模型分离,通过这种方式可以在开发过程中提高代码的复用和可维护性。
在React中,使用了组件层次结构来分离视图和数据逻辑,并通过props传递数据和事件回调来实现解耦,这也是一种常见的设计模式。
总结和展望
设计模式是一种常用的编程思想,它提供了已经被证明可行的解决方案,使我们写出的代码更加规范、易于维护和可扩展。在未来,设计模式会继续影响着软件工程的发展,同时也需要不断更新、设计更优秀的设计模式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫