大家好!欢迎来到“星辰编程理财”,今天为大家详细介绍23种设计模式,并通过实际示例代码演示它们的用法和优缺点。
在前端开发中,设计模式是一种用于解决常见问题的可重用的解决方案。它们是由经验丰富的开发人员和专家所总结和推荐的最佳实践。设计模式不仅可以提高代码的可读性和可维护性,还可以加快开发速度并降低错误的产生。
设计模式最早由计算机科学家克里斯托弗·亚历山大(Christopher Alexander)在他的书《建筑的永恒之道》(A Pattern Language)中引入。后来,设计模式逐渐被应用到软件开发领域,以提高软件系统的可扩展性和可重用性。
SOLID 是面向对象设计中常用的五个原则的缩写:
设计模式并不适用于所有情况,它们只是一种解决问题的工具。在选择使用设计模式时,我们需要考虑以下几个因素:
设计模式的发展是一个不断演化的过程。随着技术的进步和软件开发领域的发展,新的设计模式不断涌现。同时,我们也需要根据具体的项目需求和团队情况来选择合适的设计模式。以下是一些设计模式的最佳实践:
创建型模式主要关注如何创建对象,以及对象的实例化过程。它们提供了一种创建对象的方式,使得系统可以独立于对象的具体类进行实例化。
工厂模式是一种常见的创建型模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪个类。优点是封装了对象的创建过程,使客户端代码与具体类解耦。缺点是当需要添加新的产品时,需要修改工厂类的代码。
使用场景:
工厂模式适用于需要根据不同的条件创建不同类型对象的情况。比如,我们可以根据用户的不同等级,创建不同权限的用户对象。
代码示例:
interface Product {
use(): void;
}
class ConcreteProduct implements Product {
use() {
console.log('Using ConcreteProduct');
}
}
class Factory {
createProduct(): Product {
return new ConcreteProduct();
}
}
const factory = new Factory();
const product = factory.createProduct();
product.use();
抽象工厂模式是一种用于创建一系列相关或相互依赖的对象的创建型模式。它提供了一个接口,用于创建一族产品,而不需要指定具体的产品类。优点是可以在不修改现有代码的情况下引入新的产品系列,缺点是难以支持新种类的产品。
使用场景:
抽象工厂模式适用于需要创建多个相关对象,并且这些对象之间有一定约束关系的情况。比如,我们可以使用抽象工厂模式创建一个UI组件库,其中包含了多种样式和风格的按钮、输入框等组件。
代码示例:
interface AbstractProductA {
use(): void;
}
interface AbstractProductB {
use(): void;
}
class ConcreteProductA1 implements AbstractProductA {
use() {
console.log('Using ConcreteProductA1');
}
}
class ConcreteProductB1 implements AbstractProductB {
use() {
console.log('Using ConcreteProductB1');
}
}
class ConcreteProductA2 implements AbstractProductA {
use() {
console.log('Using ConcreteProductA2');
}
}
class ConcreteProductB2 implements AbstractProductB {
use() {
console.log('Using ConcreteProductB2');
}
}
interface AbstractFactory {
createProductA(): AbstractProductA;
createProductB(): AbstractProductB;
}
class ConcreteFactory1 implements AbstractFactory {
createProductA(): AbstractProductA {
return new ConcreteProductA1();
}
createProductB(): AbstractProductB {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
createProductA(): AbstractProductA {
return new ConcreteProductA2();
}
createProductB(): AbstractProductB {
return new ConcreteProductB2();
}
}
const factory1 = new ConcreteFactory1();
const productA1 = factory1.createProductA();
const productB1 = factory1.createProductB();
productA1.use();
productB1.use();
const factory2 = new ConcreteFactory2();
const productA2 = factory2.createProductA();
const productB2 = factory2.createProductB();
productA2.use();
productB2.use();
单例模式是一种创建型模式,它保证一个类只有一个实例,并提供了一个全局访问点。优点是可以节省内存,避免资源的重复创建,缺点是对于多线程环境下可能会引发竞态条件。
使用场景:
单例模式适用于需要共享一些公共资源的情况。比如,我们可以使用单例模式来创建一个全局的日志对象,在整个应用程序中都可以使用这个对象来记录日志信息。
代码示例:
class Singleton {
private static instance: Singleton;
private constructor() {}
static getInstance(): Singleton {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
use() {
console.log('Using Singleton');
}
}
const singleton1 = Singleton.getInstance();
const singleton2 = Singleton.getInstance();
console.log(singleton1 === singleton2); // true
singleton1.use();
原型模式是一种通过复制现有对象来创建新对象的创建型模式。它通过克隆原型来创建新的对象,而不需要通过实例化类。优点是可以避免重复初始化对象,缺点是需要在每个可克隆的类中实现克隆方法。
使用场景:
原型模式适用于需要创建多个相似对象的情况。比如,我们可以使用原型模式来创建一个表单验证器的原型对象,然后根据需要进行复制,从而快速创建多个表单验证器。
代码示例:
abstract class Prototype {
abstract clone(): Prototype;
}
class ConcretePrototype1 extends Prototype {
clone(): Prototype {
return new ConcretePrototype1();
}
}
class ConcretePrototype2 extends Prototype {
clone(): Prototype {
return new ConcretePrototype2();
}
}
const prototype1 = new ConcretePrototype1();
const clone1 = prototype1.clone();
console.log(prototype1 !== clone1); // true
建造者模式是一种创建型模式,它将对象的构建过程和表示分离,使同样的构建过程可以创建不同的表示。优点是可以通过相同的构建过程构建不同的产品,缺点是需要为每种表示编写具体的建造者类。
使用场景:
建造者模式适用于需要构建复杂对象的情况。比如,我们可以使用建造者模式来构建一个包含多个步骤的表单,每个步骤可以由不同的构建者来完成。
代码示例:
class Product {
private parts: string[] = [];
addPart(part: string) {
this.parts.push(part);
}
listParts() {
console.log(`Parts: ${this.parts.join(', ')}`);
}
}
interface Builder {
buildPartA(): void;
buildPartB(): void;
getProduct(): Product;
}
class ConcreteBuilder1 implements Builder {
private product: Product;
constructor() {
this.reset();
}
reset() {
this.product = new Product();
}
buildPartA() {
this.product.addPart('Part A1');
}
buildPartB() {
this.product.addPart('Part B1');
}
getProduct(): Product {
const result = this.product;
this.reset();
return result;
}
}
class ConcreteBuilder2 implements Builder {
private product: Product;
constructor() {
this.reset();
}
reset() {
this.product = new Product();
}
buildPartA() {
this.product.addPart('Part A2');
}
buildPartB() {
this.product.addPart('Part B2');
}
getProduct(): Product {
const result = this.product;
this.reset();
return result;
}
}
class Director {
private builder: Builder;
setBuilder(builder: Builder) {
this.builder = builder;
}
buildMinimalProduct() {
this.builder.buildPartA();
}
buildFullProduct() {
this.builder.buildPartA();
this.builder.buildPartB();
}
}
const director = new Director();
const builder1 = new ConcreteBuilder1();
director.setBuilder(builder1);
director.buildFullProduct();
const product1 = builder1.getProduct();
product1.listParts();
const builder2 = new ConcreteBuilder2();
director.setBuilder(builder2);
director.buildMinimalProduct();
const product2 = builder2.getProduct();
product2.listParts();
结构型模式主要关注如何组合类和对象以形成更大的结构,并提供新的功能。它们通过组合不同的类和对象来解决特定的设计问题,以实现更灵活、可扩展和可维护的系统结构。
适配器模式是一种结构型模式,它通过将一个类的接口转换成客户端所期望的接口来适应不兼容的接口。优点是可以使不兼容的类一起工作,缺点是增加了代码的复杂性。
使用场景:
当希望使用一个已经存在的类,但是它的接口不符合需求时,可以使用适配器模式将其接口转换成合适的接口。
代码示例:
interface Target {
request(): void;
}
class Adaptee {
specificRequest() {
console.log('Specific request');
}
}
class Adapter implements Target {
private adaptee: Adaptee;
constructor(adaptee: Adaptee) {
this.adaptee = adaptee;
}
request() {
this.adaptee.specificRequest();
}
}
const adaptee = new Adaptee();
const adapter = new Adapter(adaptee);
adapter.request();
桥接模式是一种结构型模式,它将抽象部分和实现部分分离,使它们可以独立地变化。优点是可以减少类的数量,提高系统的可扩展性,缺点是增加了系统的复杂性。
使用场景:
桥接模式适用于需要在抽象部分和实现部分之间存在多对多关系的情况。比如,我们可以使用桥接模式将多个颜色和形状进行组合,从而得到不同颜色和形状的组合结果。
interface Implementor {
operationImpl(): void;
}
class ConcreteImplementorA implements Implementor {
operationImpl() {
console.log('ConcreteImplementorA operation');
}
}
class ConcreteImplementorB implements Implementor {
operationImpl() {
console.log('ConcreteImplementorB operation');
}
}
abstract class Abstraction {
protected implementor: Implementor;
constructor(implementor: Implementor) {
this.implementor = implementor;
}
abstract operation(): void;
}
class RefinedAbstraction extends Abstraction {
operation() {
this.implementor.operationImpl();
}
}
const implementorA = new ConcreteImplementorA();
const abstractionA = new RefinedAbstraction(implementorA);
abstractionA.operation();
const implementorB = new ConcreteImplementorB();
const abstractionB = new RefinedAbstraction(implementorB);
abstractionB.operation();
装饰器模式是一种结构型模式,它动态地将责任附加到对象上。它提供了一种灵活的方式来扩展对象的功能。优点是可以在不改变原始对象的情况下添加新的功能,缺点是增加了类的数量。
使用场景:
装饰器模式适用于需要对一个对象进行功能扩展的情况。比如,我们可以使用装饰器模式来给一个文本编辑器添加自动保存、自动备份等功能。
代码示例:
interface Component {
operation(): void;
}
class ConcreteComponent implements Component {
operation() {
console.log('ConcreteComponent operation');
}
}
class Decorator implements Component {
protected component: Component;
constructor(component: Component) {
this.component = component;
}
operation() {
this.component.operation();
}
}
class ConcreteDecoratorA extends Decorator {
operation() {
super.operation();
this.additionalOperation();
}
additionalOperation() {
console.log('Additional operation in ConcreteDecoratorA');
}
}
class ConcreteDecoratorB extends Decorator {
operation() {
super.operation();
this.additionalOperation();
}
additionalOperation() {
console.log('Additional operation in ConcreteDecoratorB');
}
}
const component = new ConcreteComponent();
const decoratorA = new ConcreteDecoratorA(component);
decoratorA.operation();
const decoratorB = new ConcreteDecoratorB(component);
decoratorB.operation();
const decoratorAB = new ConcreteDecoratorB(decoratorA);
decoratorAB.operation();
组合模式是一种结构型模式,它将对象组织成树形结构,以表示部分-整体的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。优点是简化了客户端代码,使得新增类型的处理更加容易,缺点是限制了组合对象的类型。
使用场景:
组合模式适用于需要处理层次结构数据的情况。比如,我们可以使用组合模式来表示一个多级菜单,其中每个菜单项都可以包含子菜单。
以下是组合模式的代码示例:
abstract class Component {
protected parent: Component | null;
setParent(parent: Component | null) {
this.parent = parent;
}
getParent(): Component | null {
return this.parent;
}
add(component: Component): void {}
remove(component: Component): void {}
isComposite(): boolean {
return false;
}
abstract operation(): void;
}
class Leaf extends Component {
operation() {
console.log('Leaf operation');
}
}
class Composite extends Component {
protected children: Component[] = [];
add(component: Component) {
this.children.push(component);
component.setParent(this);
}
remove(component: Component) {
const index = this.children.indexOf(component);
if (index !== -1) {
this.children.splice(index, 1);
component.setParent(null);
}
}
isComposite(): boolean {
return true;
}
operation() {
console.log('Composite operation');
for (const child of this.children) {
child.operation();
}
}
}
const leaf1 = new Leaf();
leaf1.operation();
const leaf2 = new Leaf();
leaf2.operation();
const composite = new Composite();
composite.add(leaf1);
composite.add(leaf2);
composite.operation();
外观模式是一种结构型模式,它为一组复杂的子系统提供了一个简化的接口。通过引入一个外观类,可以减少与子系统的直接交互,从而简化了客户端代码。优点是简化了客户端代码,缺点是增加了子系统的耦合性。
使用场景:
外观模式适用于需要对一个复杂子系统进行封装的情况。比如,我们可以使用外观模式来封装一个包含多个接口调用的功能模块。
代码示例:
class SubsystemA {
operationA() {
console.log('SubsystemA operation');
}
}
class SubsystemB {
operationB() {
console.log('SubsystemB operation');
}
}
class SubsystemC {
operationC() {
console.log('SubsystemC operation');
}
}
class Facade {
private subsystemA: SubsystemA;
private subsystemB: SubsystemB;
private subsystemC: SubsystemC;
constructor() {
this.subsystemA = new SubsystemA();
this.subsystemB = new SubsystemB();
this.subsystemC = new SubsystemC();
}
operation() {
this.subsystemA.operationA();
this.subsystemB.operationB();
this.subsystemC.operationC();
}
}
const facade = new Facade();
facade.operation();
享元模式是一种结构型模式,它通过共享尽可能多的对象来最小化内存使用和对象数量。它通过将对象的外部状态与内部状态分离来实现共享。优点是减少了对象的数量,节省了内存,缺点是增加了代码的复杂性。
使用场景:
享元模式适用于需要创建大量相似对象的情况。比如,我们可以使用享元模式来创建一个图标库,其中包含了多种类型和样式的图标。
代码示例:
class Flyweight {
private sharedState: string;
constructor(sharedState: string) {
this.sharedState = sharedState;
}
operation(uniqueState: string) {
console.log(`Flyweight with shared state ${this.sharedState} and unique state ${uniqueState}`);
}
}
class FlyweightFactory {
private flyweights: { [key: string]: Flyweight } = {};
getFlyweight(sharedState: string): Flyweight {
if (!this.flyweights[sharedState]) {
this.flyweights[sharedState] = new Flyweight(sharedState);
}
return this.flyweights[sharedState];
}
}
const factory = new FlyweightFactory();
const flyweight1 = factory.getFlyweight('shared state 1');
flyweight1.operation('unique state 1');
const flyweight2 = factory.getFlyweight('shared state 2');
flyweight2.operation('unique state 2');
const flyweight3 = factory.getFlyweight('shared state 1');
flyweight3.operation('unique state 3');
console.log(flyweight1 === flyweight3); // true
代理模式是一种结构型模式,它提供了一个代理对象来控制对另一个对象的访问。通过使用代理,客户端可以间接地与真实对象进行交互。优点是可以对客户端隐藏真实对象的细节,缺点是增加了代码的复杂性。
使用场景:
代理模式适用于需要对一个对象进行控制或增强的情况。比如,我们可以使用代理模式来实现一个缓存代理,从而提高对某个对象的访问速度。
代码示例:
interface Subject {
request(): void;
}
class RealSubject implements Subject {
request() {
console.log('RealSubject request');
}
}
class Proxy implements Subject {
private realSubject: RealSubject;
constructor(realSubject: RealSubject) {
this.realSubject = realSubject;
}
request() {
this.preRequest();
this.realSubject.request();
this.postRequest();
}
preRequest() {
console.log('Proxy preRequest');
}
postRequest() {
console.log('Proxy postRequest');
}
}
const realSubject = new RealSubject();
const proxy = new Proxy(realSubject);
proxy.request();
行为型模式主要关注对象之间的通信和协作,以及对象如何分配职责和管理复杂的行为。它们描述了对象之间的交互方式,以及如何将行为分配到不同的对象中。
策略模式是一种定义一系列算法的方法,并将其封装起来,使其可以相互替换。策略模式可以使算法的变化独立于使用它的客户端。
优点:
缺点:
使用场景:
代码示例:
// 策略接口
interface Strategy {
execute(): void;
}
// 具体策略A
class ConcreteStrategyA implements Strategy {
execute() {
console.log('执行策略A');
}
}
// 具体策略B
class ConcreteStrategyB implements Strategy {
execute() {
console.log('执行策略B');
}
}
// 上下文
class Context {
private strategy: Strategy;
constructor(strategy: Strategy) {
this.strategy = strategy;
}
setStrategy(strategy: Strategy) {
this.strategy = strategy;
}
executeStrategy() {
this.strategy.execute();
}
}
// 使用策略模式
const context: Context = new Context(new ConcreteStrategyA());
context.executeStrategy();
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy();
观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生变化时,其依赖者都会收到通知并自动更新。
优点:
缺点:
使用场景:
代码示例:
// 被观察者接口
interface Subject {
registerObserver(observer: Observer): void;
removeObserver(observer: Observer): void;
notifyObservers(): void;
}
// 观察者接口
interface Observer {
update(data: any): void;
}
// 具体被观察者
class ConcreteSubject implements Subject {
private observers: Observer[] = [];
private data: any;
registerObserver(observer: Observer) {
this.observers.push(observer);
}
removeObserver(observer: Observer) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
}
notifyObservers() {
for (const observer of this.observers) {
observer.update(this.data);
}
}
setData(data: any) {
this.data = data;
this.notifyObservers();
}
}
// 具体观察者A
class ConcreteObserverA implements Observer {
update(data: any) {
console.log('观察者A收到通知,数据:', data);
}
}
// 具体观察者B
class ConcreteObserverB implements Observer {
update(data: any) {
console.log('观察者B收到通知,数据:', data);
}
}
// 使用观察者模式
const subject: Subject = new ConcreteSubject();
const observerA: Observer = new ConcreteObserverA();
const observerB: Observer = new ConcreteObserverB();
subject.registerObserver(observerA);
subject.registerObserver(observerB);
subject.setData('hello');
责任链模式是一种将请求的发送和接收解耦的设计模式,多个对象按照顺序形成一条链,请求沿着链传递,直到有一个对象处理它。
优点:
缺点:
使用场景:
代码示例:
// 请求类
class Request {
private type: string;
constructor(type: string) {
this.type = type;
}
getType() {
return this.type;
}
}
// 处理者抽象类
abstract class Handler {
private nextHandler: Handler;
setNextHandler(nextHandler: Handler) {
this.nextHandler = nextHandler;
}
handleRequest(request: Request) {
if (this.canHandleRequest(request)) {
this.handle(request);
} else if (this.nextHandler) {
this.nextHandler.handleRequest(request);
} else {
console.log('无处理者可以处理该请求');
}
}
protected abstract canHandleRequest(request: Request): boolean;
protected abstract handle(request: Request): void;
}
// 具体处理者A
class ConcreteHandlerA extends Handler {
protected canHandleRequest(request: Request): boolean {
return request.getType() === 'A';
}
protected handle(request: Request): void {
console.log('处理者A处理请求');
}
}
// 具体处理者B
class ConcreteHandlerB extends Handler {
protected canHandleRequest(request: Request): boolean {
return request.getType() === 'B';
}
protected handle(request: Request): void {
console.log('处理者B处理请求');
}
}
// 使用责任链模式
const handlerA: Handler = new ConcreteHandlerA();
const handlerB: Handler = new ConcreteHandlerB();
handlerA.setNextHandler(handlerB);
const requestA: Request = new Request('A');
handlerA.handleRequest(requestA);
const requestB: Request = new Request('B');
handlerA.handleRequest(requestB);
命令模式是一种将请求封装成对象的设计模式,使得请求的发送者与请求的接收者之间解耦。命令模式可以将请求参数化,将请求操作的对象和被调用者分离。
优点:
缺点:
使用场景:
代码示例:
// 命令接口
interface Command {
execute(): void;
}
// 具体命令A
class ConcreteCommandA implements Command {
private receiver: Receiver;
constructor(receiver: Receiver) {
this.receiver = receiver;
}
execute() {
this.receiver.actionA();
}
}
// 具体命令B
class ConcreteCommandB implements Command {
private receiver: Receiver;
constructor(receiver: Receiver) {
this.receiver = receiver;
}
execute() {
this.receiver.actionB();
}
}
// 接收者
class Receiver {
actionA() {
console.log('接收者执行操作A');
}
actionB() {
console.log('接收者执行操作B');
}
}
// 请求者
class Invoker {
private commands: Command[] = [];
addCommand(command: Command) {
this.commands.push(command);
}
executeCommands() {
for (const command of this.commands) {
command.execute();
}
}
}
// 使用命令模式
const receiver: Receiver = new Receiver();
const commandA: Command = new ConcreteCommandA(receiver);
const commandB: Command = new ConcreteCommandB(receiver);
const invoker: Invoker = new Invoker();
invoker.addCommand(commandA);
invoker.addCommand(commandB);
invoker.executeCommands();
迭代器模式是一种顺序访问集合对象元素的方法,不需要知道集合对象的底层实现。
优点:
缺点:
使用场景:
代码示例:
// 迭代器接口
interface Iterator<T> {
hasNext(): boolean;
next(): T;
}
// 具体迭代器
class ConcreteIterator<T> implements Iterator<T> {
private collection: T[];
private index: number = 0;
constructor(collection: T[]) {
this.collection = collection;
}
hasNext(): boolean {
return this.index < this.collection.length;
}
next(): T {
return this.collection[this.index++];
}
}
// 集合类接口
interface Aggregate<T> {
createIterator(): Iterator<T>;
}
// 具体集合类
class ConcreteAggregate<T> implements Aggregate<T> {
private collection: T[];
constructor(collection: T[]) {
this.collection = collection;
}
createIterator(): Iterator<T> {
return new ConcreteIterator(this.collection);
}
}
// 使用迭代器模式
const collection: string[] = ['a', 'b', 'c'];
const aggregate: Aggregate<string> = new ConcreteAggregate(collection);
const iterator: Iterator<string> = aggregate.createIterator();
while (iterator.hasNext()) {
console.log(iterator.next());
}
中介者模式定义了一个中介对象,该对象封装了一系列对象之间的交互方式。通过使用中介者,对象之间的通信将通过中介者进行,而不是直接彼此交互。
优点:
缺点:
使用场景:
代码示例:
// 中介者接口
interface Mediator {
send(message: string, colleague: Colleague): void;
}
// 同事类抽象类
abstract class Colleague {
protected mediator: Mediator;
constructor(mediator: Mediator) {
this.mediator = mediator;
}
abstract receive(message: string): void;
abstract send(message: string): void;
}
// 具体中介者
class ConcreteMediator implements Mediator {
private colleagueA: Colleague;
private colleagueB: Colleague;
setColleagueA(colleague: Colleague) {
this.colleagueA = colleague;
}
setColleagueB(colleague: Colleague) {
this.colleagueB = colleague;
}
send(message: string, colleague: Colleague) {
if (colleague === this.colleagueA) {
this.colleagueB.receive(message);
} else if (colleague === this.colleagueB) {
this.colleagueA.receive(message);
}
}
}
// 具体同事A
class ConcreteColleagueA extends Colleague {
receive(message: string) {
console.log('同事A收到消息:', message);
}
send(message: string) {
this.mediator.send(message, this);
}
}
// 具体同事B
class ConcreteColleagueB extends Colleague {
receive(message: string) {
console.log('同事B收到消息:', message);
}
send(message: string) {
this.mediator.send(message, this);
}
}
// 使用中介者模式
const mediator: Mediator = new ConcreteMediator();
const colleagueA: Colleague = new ConcreteColleagueA(mediator);
const colleagueB: Colleague = new ConcreteColleagueB(mediator);
mediator.setColleagueA(colleagueA);
mediator.setColleagueB(colleagueB);
colleagueA.send('hello');
colleagueB.send('world');
备忘录模式是一种保存对象状态的设计模式,它允许在不破坏封装性的前提下,捕获并保存对象内部的状态,并且可以在以后恢复到该状态。
优点:
缺点:
使用场景:
代码示例:
// 备忘录
class Memento {
private state: string;
constructor(state: string) {
this.state = state;
}
getState() {
return this.state;
}
}
// 原发器
class Originator {
private state: string;
setState(state: string) {
this.state = state;
}
getState() {
return this.state;
}
createMemento(): Memento {
return new Memento(this.state);
}
restoreMemento(memento: Memento) {
this.state = memento.getState();
}
}
// 管理者
class Caretaker {
private mementos: Memento[] = [];
addMemento(memento: Memento) {
this.mementos.push(memento);
}
getMemento(index: number) {
return this.mementos[index];
}
}
// 使用备忘录模式
const originator: Originator = new Originator();
const caretaker: Caretaker = new Caretaker();
originator.setState('State 1');
console.log('当前状态:', originator.getState());
const memento: Memento = originator.createMemento();
caretaker.addMemento(memento);
originator.setState('State 2');
console.log('当前状态:', originator.getState());
originator.restoreMemento(caretaker.getMemento(0));
console.log('恢复后的状态:', originator.getState());
解释器模式是一种用于解决特定类型问题的行为模式,它定义了一种语言语法的表示,并解释该语法。
优点:
缺点:
使用场景:
代码示例:
// 上下文
class Context {
private input: string;
private output: number;
constructor(input: string) {
this.input = input;
}
getInput() {
return this.input;
}
setInput(input: string) {
this.input = input;
}
getOutput() {
return this.output;
}
setOutput(output: number) {
this.output = output;
}
}
// 抽象表达式
abstract class Expression {
abstract interpret(context: Context): void;
}
// 终结符表达式
class TerminalExpression extends Expression {
interpret(context: Context) {
context.setOutput(parseInt(context.getInput()));
}
}
// 非终结符表达式
class NonterminalExpression extends Expression {
private expression1: Expression;
private expression2: Expression;
constructor(expression1: Expression, expression2: Expression) {
super();
this.expression1 = expression1;
this.expression2 = expression2;
}
interpret(context: Context) {
const input = context.getInput();
const index = input.indexOf(' ');
if (index !== -1) {
const subInput1 = input.substring(0, index);
const subInput2 = input.substring(index + 1);
context.setInput(subInput2);
this.expression1.interpret(context);
this.expression2.interpret(context);
}
}
}
// 使用解释器模式
const expression1: Expression = new TerminalExpression();
const expression2: Expression = new NonterminalExpression(expression1, expression1);
const context: Context = new Context('100 200');
expression2.interpret(context);
console.log('解释结果:', context.getOutput());
状态模式是一种将对象的行为封装成不同状态的设计模式,使得对象在不同状态下可以改变其行为。
优点:
缺点:
使用场景:
代码示例:
// 状态接口
interface State {
handle(context: Context): void;
}
// 具体状态A
class ConcreteStateA implements State {
handle(context: Context) {
console.log('当前状态为A,将转换到下一个状态B');
context.setState(new ConcreteStateB());
}
}
// 具体状态B
class ConcreteStateB implements State {
handle(context: Context) {
console.log('当前状态为B,将转换到下一个状态A');
context.setState(new ConcreteStateA());
}
}
// 上下文
class Context {
private state: State;
constructor() {
this.state = new ConcreteStateA();
}
setState(state: State) {
this.state = state;
}
request() {
this.state.handle(this);
}
}
// 使用状态模式
const context: Context = new Context();
context.request();
context.request();
context.request();
模板方法模式是一种基于继承的设计模式,它定义了一个算法的骨架,而将一些步骤的实现延迟到子类中。模板方法模式提供了一种封装算法的方式,使得子类可以在不改变算法结构的情况下,重新定义算法中某些步骤的具体实现。
优点:
缺点:
使用场景:
代码示例:
// 抽象类
abstract class AbstractClass {
// 模板方法
public templateMethod(): void {
this.baseOperation1();
this.requiredOperation1();
this.baseOperation2();
this.hook();
}
// 基本操作1
protected baseOperation1(): void {
console.log('抽象类中的基本操作1');
}
// 基本操作2
protected baseOperation2(): void {
console.log('抽象类中的基本操作2');
}
// 钩子操作
protected hook(): void {}
// 必需的操作1,延迟到子类中实现
protected abstract requiredOperation1(): void;
}
// 具体类A
class ConcreteClassA extends AbstractClass {
protected requiredOperation1(): void {
console.log('具体类A中的必需操作1');
}
}
// 具体类B
class ConcreteClassB extends AbstractClass {
protected requiredOperation1(): void {
console.log('具体类B中的必需操作1');
}
// 重写钩子操作
protected hook(): void {
console.log('具体类B中的钩子操作');
}
}
// 客户端
const concreteClassA = new ConcreteClassA();
concreteClassA.templateMethod();
// 输出:
// 抽象类中的基本操作1
// 具体类A中的必需操作1
// 抽象类中的基本操作2
const concreteClassB = new ConcreteClassB();
concreteClassB.templateMethod();
// 输出:
// 抽象类中的基本操作1
// 具体类B中的必需操作1
// 抽象类中的基本操作2
// 具体类B中的钩子操作
访问者模式是一种将算法与对象结构分离的设计模式,它可以在不改变对象结构的前提下,增加新的操作。访问者模式通过定义一个访问者接口和多个具体访问者,来实现对不同对象结构的访问。
优点:
缺点:
使用场景:
代码示例:
// 抽象访问者
interface Visitor {
visitConcreteElementA(element: ConcreteElementA): void;
visitConcreteElementB(element: ConcreteElementB): void;
}
// 具体访问者1
class ConcreteVisitor1 implements Visitor {
public visitConcreteElementA(element: ConcreteElementA): void {
console.log('具体访问者1访问具体元素A');
element.operationA();
}
public visitConcreteElementB(element: ConcreteElementB): void {
console.log('具体访问者1访问具体元素B');
element.operationB();
}
}
// 具体访问者2
class ConcreteVisitor2 implements Visitor {
public visitConcreteElementA(element: ConcreteElementA): void {
console.log('具体访问者2访问具体元素A');
element.operationA();
}
public visitConcreteElementB(element: ConcreteElementB): void {
console.log('具体访问者2访问具体元素B');
element.operationB();
}
}
// 抽象元素
interface Element {
accept(visitor: Visitor): void;
}
// 具体元素A
class ConcreteElementA implements Element {
public accept(visitor: Visitor): void {
visitor.visitConcreteElementA(this);
}
public operationA(): void {
console.log('具体元素A的操作');
}
}
// 具体元素B
class ConcreteElementB implements Element {
public accept(visitor: Visitor): void {
visitor.visitConcreteElementB(this);
}
public operationB(): void {
console.log('具体元素B的操作');
}
}
// 对象结构
class ObjectStructure {
private elements: Element[] = [];
public attach(element: Element): void {
this.elements.push(element);
}
public detach(element: Element): void {
const index = this.elements.indexOf(element);
if (index !== -1) {
this.elements.splice(index, 1);
}
}
public accept(visitor: Visitor): void {
for (const element of this.elements) {
element.accept(visitor);
}
}
}
// 客户端
const objectStructure = new ObjectStructure();
objectStructure.attach(new ConcreteElementA());
objectStructure.attach(new ConcreteElementB());
const visitor1 = new ConcreteVisitor1();
objectStructure.accept(visitor1);
// 输出:
// 具体访问者1访问具体元素A
// 具体元素A的操作
// 具体访问者1访问具体元素B
// 具体元素B的操作
const visitor2 = new ConcreteVisitor2();
objectStructure.accept(visitor2);
// 输出:
// 具体访问者2访问具体元素A
// 具体元素A的操作
// 具体访问者2访问具体元素B
// 具体元素B的操作
以下是一个使用观察者模式解决实际问题的案例:
// 定义一个主题接口
interface Subject {
attach(observer: Observer): void;
detach(observer: Observer): void;
notify(): void;
}
// 定义一个观察者接口
interface Observer {
update(): void;
}
// 实现主题
class ConcreteSubject implements Subject {
private observers: Observer[] = [];
attach(observer: Observer): void {
this.observers.push(observer);
}
detach(observer: Observer): void {
const index = this.observers.indexOf(observer);
if (index >= 0) {
this.observers.splice(index, 1);
}
}
notify(): void {
for (const observer of this.observers) {
observer.update();
}
}
}
// 实现观察者
class ConcreteObserver implements Observer {
update(): void {
console.log('观察者收到通知');
}
}
// 使用观察者模式
const subject = new ConcreteSubject();
const observer = new ConcreteObserver();
subject.attach(observer);
subject.notify();
在项目中选择和应用设计模式时,我们可以按照以下步骤进行:
总之,设计模式是前端开发中重要的工具和技巧,可以提高代码的可读性、可维护性和可扩展性。熟悉并应用设计模式将使我们的代码更加优雅和高效。