设计模式

141 阅读10分钟

设计模式

创建型模式(Creational Patterns) 创建型模式是用来处理对象创建的模式,这些模式可以根据不同的情况,使用不同的方式来创建对象。创建型模式包括:

  1. 抽象工厂模式(Abstract Factory Pattern)
  2. 单例模式(Singleton Pattern)
  3. 原型模式(Prototype Pattern)
  4. 建造者模式(Builder Pattern)

结构型模式(Structural Patterns)

结构型模式是用来处理对象组合的模式,这些模式可以让你在设计时更好地组合对象以获得更好的性能。结构型模式包括:

  1. 适配器模式(Adapter Pattern)
  2. 装饰器模式(Decorator Pattern)
  3. 外观模式(Facade Pattern)
  4. 代理模式(Proxy Pattern)
  5. 桥接模式(Bridge Pattern)
  6. 组合模式(Composite Pattern)
  7. 享元模式(Flyweight Pattern)

行为型模式(Behavioral Patterns)

行为型模式是用来处理对象之间的通信的模式,这些模式可以让你更好地控制对象之间的通信以及流程。行为型模式包括:

  1. 策略模式(Strategy Pattern)
  2. 状态模式(State Pattern)
  3. 模板方法模式(Template Method Pattern)
  4. 命令模式(Command Pattern)
  5. 迭代器模式(Iterator Pattern)
  6. 访问者模式(Visitor Pattern)
  7. 观察者模式(Observer Pattern)
  8. 中介者模式(Mediator Pattern)
  9. 备忘录模式(Memento Pattern)
  10. 解释器模式(Interpreter Pattern)
  11. 订阅-发布模式(Publish-Subscribe Pattern)
  12. 责任链模式(Chain of Responsibility Pattern)

1. 工厂模式(Factory Pattern)

工厂模式(Factory Pattern)

工厂模式是一种创建对象的模式,根据不同的参数返回不同类的实例。

function ShapeFactory() {}

ShapeFactory.prototype.createShape = function(type) {
  if (type === "circle") {
    return new Circle();
  } else if (type === "rectangle") {
    return new Rectangle();
  } else if (type === "triangle") {
    return new Triangle();
  } else {
    return null;
  }
};

function Circle() {
  this.name = "Circle";
}

function Rectangle() {
  this.name = "Rectangle";
}

function Triangle() {
  this.name = "Triangle";
}

const shapeFactory = new ShapeFactory();

const circle = shapeFactory.createShape("circle");
const rectangle = shapeFactory.createShape("rectangle");
const triangle = shapeFactory.createShape("triangle");

console.log(circle.name); // "Circle"
console.log(rectangle.name); // "Rectangle"
console.log(triangle.name); // "Triangle"

抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式是一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

function Button() {}

Button.prototype.render = function() {
  console.log("Button rendered");
};

function Checkbox() {}

Checkbox.prototype.render = function() {
  console.log("Checkbox rendered");
};

function MacButton() {}

MacButton.prototype = Object.create(Button.prototype);
MacButton.prototype.constructor = MacButton;

MacButton.prototype.render = function() {
  console.log("Mac button rendered");
};

function MacCheckbox() {}

MacCheckbox.prototype = Object.create(Checkbox.prototype);
MacCheckbox.prototype.constructor = MacCheckbox;

MacCheckbox.prototype.render = function() {
  console.log("Mac checkbox rendered");
};

function WinButton() {}

WinButton.prototype = Object.create(Button.prototype);
WinButton.prototype.constructor = WinButton;

WinButton.prototype.render = function() {
  console.log("Windows button rendered");
};

function WinCheckbox() {}

WinCheckbox.prototype = Object.create(Checkbox.prototype);
WinCheckbox.prototype.constructor = WinCheckbox;

WinCheckbox.prototype.render = function() {
  console.log("Windows checkbox rendered");
};

function MacFactory() {}

MacFactory.prototype.createButton = function() {
  return new MacButton();
};

MacFactory.prototype.createCheckbox = function() {
  return new MacCheckbox();
};

function WinFactory() {}

WinFactory.prototype.createButton = function() {
  return new WinButton();
};

WinFactory.prototype.createCheckbox = function() {
  return new WinCheckbox();
};

function Application(factory) {
  this.factory = factory;
  this.button = null;
  this.checkbox = null;
}

Application.prototype.createUI = function() {
  this.button = this.factory.createButton();
  this.checkbox = this.factory.createCheckbox();
};

Application.prototype.renderUI = function() {
  this.button.render();
  this.checkbox.render();
};

const macFactory = new MacFactory();
const winFactory = new WinFactory();

const macApp = new Application(macFactory);
const winApp = new Application(winFactory);

macApp.createUI();
macApp.renderUI();

winApp.createUI();
winApp.renderUI();

2. 单例模式(Singleton Pattern)

单例模式是一种只允许创建单个实例的模式。

const Singleton = (function() {
  let instance;

  function createInstance() {
    const object = new Object("I am the instance");
    return object;
  }

  return {
    getInstance: function() {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();

console.log(instance1 === instance2); // true

3. 原型模式(Prototype Pattern)

原型模式是一种通过复制现有对象来创建新对象的模式。

// 定义原型对象
const carPrototype = {
  wheels: 4,
  drive() {
    console.log("Driving the car...");
  },
};
// 创建新车
const car1 = Object.create(carPrototype);
console.log(car1.wheels); // 输出: 4
car1.drive(); // 输出: "Driving the car..."
// 克隆现有车
const car2 = Object.create(carPrototype);
car2.wheels = 3;
console.log(car2.wheels); // 输出: 3
car2.drive(); // 输出: "Driving the car..."

4. 建造者模式(Builder Pattern)

用于将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式通常用于创建具有多个可选参数和组件的对象。

// 产品类
class Product {
  private partA: string;
  private partB: string;
  private partC: string;

  constructor(builder: Builder) {
    this.partA = builder.partA;
    this.partB = builder.partB;
    this.partC = builder.partC;
  }

  public getPartA(): string {
    return this.partA;
  }

  public getPartB(): string {
    return this.partB;
  }

  public getPartC(): string {
    return this.partC;
  }
}

// 建造者接口
interface Builder {
  partA: string;
  partB: string;
  partC: string;
}

// 具体建造者
class ConcreteBuilder implements Builder {
  public partA: string;
  public partB: string;
  public partC: string;

  constructor() {
    this.reset();
  }

  public reset(): void {
    this.partA = '';
    this.partB = '';
    this.partC = '';
  }

  public setPartA(value: string): this {
    this.partA = value;
    return this;
  }

  public setPartB(value: string): this {
    this.partB = value;
    return this;
  }

  public setPartC(value: string): this {
    this.partC = value;
    return this;
  }

  public build(): Product {
    const product = new Product(this);
    this.reset();
    return product;
  }
}

// 客户端代码
function clientCode() {
  const builder = new ConcreteBuilder();

  const product1 = builder
    .setPartA('PartA1')
    .setPartB('PartB1')
    .setPartC('PartC1')
    .build();

  console.log(product1.getPartA()); // 输出:PartA1
  console.log(product1.getPartB()); // 输出:PartB1
  console.log(product1.getPartC()); // 输出:PartC1

  const product2 = builder
    .setPartA('PartA2')
    .setPartB('PartB2')
    .build();

  console.log(product2.getPartA()); // 输出:PartA2
  console.log(product2.getPartB()); // 输出:PartB2
  console.log(product2.getPartC()); // 输出:(默认值)
}

clientCode();

5. 适配器模式(Adapter Pattern)

适配器模式是一种将不符合接口要求的类转换为符合接口要求的类的模式.

function LegacyRectangle(width, height) {
  this.width = width;
  this.height = height;
}

LegacyRectangle.prototype.getArea = function() {
  return this.width * this.height;
};

function RectangleAdapter(rectangle) {
  this.rectangle = rectangle;
}

RectangleAdapter.prototype.getArea = function() {
  return this.rectangle.getArea();
};

const legacyRectangle = new LegacyRectangle(4, 5);
const adapter = new RectangleAdapter(legacyRectangle);

console.log(adapter.getArea()); // 20

6. 装饰器模式(Decorator Pattern)

装饰器模式是一种在不改变对象自身的基础上,动态地给对象添加新的功能的模式。

function Coffee() {}

Coffee.prototype.cost = function() {
  return 10;
};

function Milk(coffee) {
  this.coffee = coffee;
}

Milk.prototype.cost = function() {
  return this.coffee.cost() + 2;
};

function Sugar(coffee) {
  this.coffee = coffee;
}

Sugar.prototype.cost = function() {
  return this.coffee.cost() + 1;
};

let coffee = new Coffee();
coffee = new Milk(coffee);
coffee = new Sugar(coffee);

console.log(coffee.cost()); // 13

7. 外观模式(Facade Pattern)

外观模式是一种为复杂的子系统提供一个简单接口的模式。

function CPU() {}

CPU.prototype.start = function() {
  console.log("CPU started");
};

function Memory() {}

Memory.prototype.load = function() {
  console.log("Memory loaded");
};

function HardDrive() {}

HardDrive.prototype.read = function() {
  console.log("Hard drive read");
};

function ComputerFacade() {
  this.cpu = new CPU();
  this.memory = new Memory();
  this.hardDrive = new HardDrive();
}

ComputerFacade.prototype.start = function() {
  this.cpu.start();
  this.memory.load();
  this.hardDrive.read();
};

const computer = new ComputerFacade();
computer.start(); // CPU started, Memory loaded, Hard drive read

8. 代理模式(Proxy Pattern)

代理模式是一种为其他对象提供一种代理以控制对这个对象的访问的模式。

function RealImage(filename) {
  this.filename = filename;
  this.loadFromDisk = function() {
    console.log("Loading " + this.filename);
  };
  this.display = function() {
    console.log("Displaying " + this.filename);
  };
}

function ProxyImage(filename) {
  this.filename = filename;
  this.realImage = null;
  this.display = function() {
    if (!this.realImage) {
      this.realImage = new RealImage(this.filename);
    }
    this.realImage.display();
  };
}

const image1 = new ProxyImage("image1.jpg");
const image2 = new ProxyImage("image2.jpg");

image1.display(); // Loading image1.jpg, Displaying image1.jpg
image1.display(); // Displaying image1.jpg
image2.display(); // Loading image2.jpg, Displaying image2.jpg
image2.display(); // Displaying image2.jpg

9. 桥接模式(Bridge Pattern)

// 抽象类
abstract class Abstraction {
  protected implementation: Implementation;

  constructor(implementation: Implementation) {
    this.implementation = implementation;
  }

  public operation(): string {
    return this.implementation.operationImplementation();
  }
}

// 具体抽象类
class RefinedAbstraction extends Abstraction {
  public operation(): string {
    return `Refined ${super.operation()}`;
  }
}

// 实现接口
interface Implementation {
  operationImplementation(): string;
}

// 具体实现类
class ConcreteImplementation implements Implementation {
  public operationImplementation(): string {
    return 'ConcreteImplementation';
  }
}

// 客户端代码
function clientCode() {
  const implementation = new ConcreteImplementation();
  const abstraction = new RefinedAbstraction(implementation);

  console.log(abstraction.operation()); // 输出:Refined ConcreteImplementation
}

clientCode();

10. 组合模式(Composite Pattern)

将对象组合成树形结构来表示部分-整体层次结构。这使得客户端可以统一对待单个对象和组合对象,从而简化了客户端代码。

// 组件接口
interface Component {
  operation(): string;
}

// 叶子组件
class Leaf implements Component {
  public operation(): string {
    return 'Leaf';
  }
}

// 组合组件
class Composite implements Component {
  private children: Component[] = [];

  public add(child: Component): void {
    this.children.push(child);
  }

  public remove(child: Component): void {
    const index = this.children.indexOf(child);
    if (index !== -1) {
      this.children.splice(index, 1);
    }
  }

  public operation(): string {
    let result = 'Composite: ';
    for (const child of this.children) {
      result += child.operation() + ' ';
    }
    return result;
  }
}

// 客户端代码
function clientCode() {
  const composite = new Composite();
  const leaf1 = new Leaf();
  const leaf2 = new Leaf();

  composite.add(leaf1);
  composite.add(leaf2);

  console.log(composite.operation()); // 输出:Composite: Leaf Leaf

  const composite2 = new Composite();
  const leaf3 = new Leaf();

  composite2.add(leaf3);
  composite.add(composite2);

  console.log(composite.operation()); // 输出:Composite: Leaf Leaf Composite: Leaf
}

clientCode();

11. 享元模式(Flyweight Pattern)

享元模式是一种通过共享对象来减少内存使用的模式。

function Flyweight() {}

Flyweight.prototype.operation = function() {
  throw new Error("Not implemented");
};

function ConcreteFlyweight() {}

ConcreteFlyweight.prototype = Object.create(Flyweight.prototype);
ConcreteFlyweight.prototype.constructor = ConcreteFlyweight;

ConcreteFlyweight.prototype.operation = function() {
  console.log("Concrete flyweight operation");
};

function FlyweightFactory() {
  this.flyweights = {};
}

FlyweightFactory.prototype.getFlyweight = function(key) {
  if (this.flyweights[key]) {
    return this.flyweights[key];
  } else {
    const flyweight = new ConcreteFlyweight();
    this.flyweights[key] = flyweight;
    return flyweight;
  }
};

const factory = new FlyweightFactory();
const flyweight1 = factory.getFlyweight("key1");
const flyweight2 = factory.getFlyweight("key2");
const flyweight3 = factory.getFlyweight("key1");

flyweight1.operation(); // Concrete flyweight operation
flyweight2.operation(); // Concrete flyweight operation
flyweight3.operation(); // Concrete flyweight operation

console.log(flyweight1 === flyweight2); // false
console.log(flyweight1 === flyweight3); // true

12. 策略模式(Strategy Pattern)

策略模式是一种定义一系列算法的模式,从而使得可以在运行时选择其中一个算法解决一个问题。

function Strategy() {}

Strategy.prototype.execute = function(num1, num2) {
  throw new Error("Not implemented");
};

function AddStrategy() {}

AddStrategy.prototype = Object.create(Strategy.prototype);
AddStrategy.prototype.constructor = AddStrategy;

AddStrategy.prototype.execute = function(num1, num2) {
  return num1 + num2;
};

function SubtractStrategy() {}

SubtractStrategy.prototype = Object.create(Strategy.prototype);
SubtractStrategy.prototype.constructor = SubtractStrategy;

SubtractStrategy.prototype.execute = function(num1, num2) {
  return num1 - num2;
};

function Calculator(strategy) {
  this.strategy = strategy;
}

Calculator.prototype.executeStrategy = function(num1, num2) {
  return this.strategy.execute(num1, num2);
};

const calculator = new Calculator(new AddStrategy());
console.log(calculator.executeStrategy(10, 5)); // 15

calculator.strategy = new SubtractStrategy();
console.log(calculator.executeStrategy(10, 5)); // 5

13. 状态模式(State Pattern)

状态模式是一种允许对象在其内部状态发生改变时改变它的行为的模式。

function State() {}

State.prototype.handle = function() {
  throw new Error("Not implemented");
};

function StartState() {}

StartState.prototype = Object.create(State.prototype);
StartState.prototype.constructor = StartState;

StartState.prototype.handle = function() {
  console.log("Start state");
};

function StopState() {}

StopState.prototype = Object.create(State.prototype);
StopState.prototype.constructor = StopState;

StopState.prototype.handle = function() {
  console.log("Stop state");
};

function Context(state) {
  this.state = state;
}

Context.prototype.setState = function(state) {
  this.state = state;
};

Context.prototype.request = function() {
  this.state.handle();
};

const context = new Context(new StartState());
context.request(); // Start state

context.setState(new StopState());
context.request(); // Stop state

14.模板方法模式(Template Method Pattern)

模板方法模式是一种定义算法框架的模式,具体实现由子类决定。

function Game() {}

Game.prototype.initialize = function() {
  throw new Error("Not implemented");
};

Game.prototype.startPlay = function() {
  throw new Error("Not implemented");
};

Game.prototype.endPlay = function() {
  throw new Error("Not implemented");
};

Game.prototype.play = function() {
  this.initialize();
  this.startPlay();
  this.endPlay();
};

function Cricket() {}

Cricket.prototype = Object.create(Game.prototype);
Cricket.prototype.constructor = Cricket;

Cricket.prototype.initialize = function() {
  console.log("Cricket game initialized");
};

Cricket.prototype.startPlay = function() {
  console.log("Cricket game started");
};

Cricket.prototype.endPlay = function() {
  console.log("Cricket game ended");
};

function Football() {}

Football.prototype = Object.create(Game.prototype);
Football.prototype.constructor = Football;

Football.prototype.initialize = function() {
  console.log("Football game initialized");
};

Football.prototype.startPlay = function() {
  console.log("Football game started");
};

Football.prototype.endPlay = function() {
  console.log("Football game ended");
};

const cricket = new Cricket();
cricket.play();

const football = new Football();
football.play();

15.命令模式(Command Pattern)

命令模式是一种将请求封装为对象,从而允许使用不同的请求、队列或日志来参数化其他对象的模式。

function Receiver() {
  this.execute = function() {
    console.log("Receiver execute");
  };
}

function Command(receiver) {
  this.receiver = receiver;
}

Command.prototype.execute = function() {
  throw new Error("Not implemented");
};

function ConcreteCommand(receiver) {
  Command.call(this, receiver);
}

ConcreteCommand.prototype = Object.create(Command.prototype);
ConcreteCommand.prototype.constructor = ConcreteCommand;

ConcreteCommand.prototype.execute = function() {
  this.receiver.execute();
};

function Invoker() {
  this.command = null;
}

Invoker.prototype.setCommand = function(command) {
  this.command = command;
};

Invoker.prototype.executeCommand = function() { this.command.execute(); };

const receiver = new Receiver(); const command = new ConcreteCommand(receiver); const invoker = new Invoker();

invoker.setCommand(command); invoker.executeCommand(); // Receiver execute

16.迭代器模式(Iterator Pattern)

迭代器模式是一种提供一种方法顺序访问一个聚合对象中各个元素的模式,而又不暴露该对象的内部表示。

function Iterator(items) {
  this.index = 0;
  this.items = items;
}

Iterator.prototype.hasNext = function() {
  return this.index < this.items.length;
};

Iterator.prototype.next = function() {
  return this.items[this.index++];
};

function Aggregate() {}

Aggregate.prototype.createIterator = function() {
  throw new Error("Not implemented");
};

function ConcreteAggregate() {
  this.items = [];
}

ConcreteAggregate.prototype = Object.create(Aggregate.prototype);
ConcreteAggregate.prototype.constructor = ConcreteAggregate;

ConcreteAggregate.prototype.createIterator = function() {
  return new Iterator(this.items);
};

ConcreteAggregate.prototype.addItem = function(item) {
  this.items.push(item);
};

const aggregate = new ConcreteAggregate();
aggregate.addItem("Item 1");
aggregate.addItem("Item 2");
aggregate.addItem("Item 3");

const iterator = aggregate.createIterator();
while (iterator.hasNext()) {
  console.log(iterator.next());
}

17.访问者模式(Visitor Pattern)

访问者模式是一种将算法与对象结构分离的模式,使得算法可以独立于对象结构地变化。

function ComputerPart() {}

ComputerPart.prototype.accept = function(visitor) {
  throw new Error("Not implemented");
};

function Keyboard() {}

Keyboard.prototype = Object.create(ComputerPart.prototype);
Keyboard.prototype.constructor = Keyboard;

Keyboard.prototype.accept = function(visitor) {
  visitor.visit(this);
};

function Monitor() {}

Monitor.prototype = Object.create(ComputerPart.prototype);
Monitor.prototype.constructor = Monitor;

Monitor.prototype.accept = function(visitor) {
  visitor.visit(this);
};

function Mouse() {}

Mouse.prototype = Object.create(ComputerPart.prototype);
Mouse.prototype.constructor = Mouse;

Mouse.prototype.accept = function(visitor) {
  visitor.visit(this);
};

function Computer() {
  this.parts = [new Mouse(), new Keyboard(), new Monitor()];
}

Computer.prototype.accept = function(visitor) {
  for (let i = 0; i < this.parts.length; i++) {
    this.parts[i].accept(visitor);
  }
  visitor.visit(this);
};

function ComputerPartVisitor() {}

ComputerPartVisitor.prototype.visit = function(part) {
  throw new Error("Not implemented");
};

function ComputerPartDisplayVisitor() {}

ComputerPartDisplayVisitor.prototype = Object.create(ComputerPartVisitor.prototype);
ComputerPartDisplayVisitor.prototype.constructor = ComputerPartDisplayVisitor;

ComputerPartDisplayVisitor.prototype.visit = function(part) {
  console.log("Displaying " + part.constructor.name);
};

const computer = new Computer();
const visitor = new ComputerPartDisplayVisitor();
computer.accept(visitor);

18. 观察者模式(Observer Pattern)

观察者模式是一种当对象间存在一对多关系时,让多个观察者对象同时监听某一个主题对象的状态变化的模式。

function Subject() {
  this.observers = [];
}

Subject.prototype.addObserver = function(observer) {
  this.observers.push(observer);
};

Subject.prototype.removeObserver = function(observer) {
  const index = this.observers.indexOf(observer);
  if (index !== -1) {
    this.observers.splice(index, 1);
  }
};

Subject.prototype.notifyObservers = function() {
  for (let i = 0; i < this.observers.length; i++) {
    this.observers[i].update();
  }
};

function Observer(name, subject) {
  this.name = name;
  this.subject = subject;
  this.update = function() {
    console.log(this.name + " notified of " + this.subject.name);
  };
}

const subject = new Subject();
const observer1 = new Observer("Observer 1", subject);
const observer2 = new Observer("Observer 2", subject);
const observer3 = new Observer("Observer 3", subject);

subject.addObserver(observer1);
subject.addObserver(observer2);
subject.addObserver(observer3);

subject.notifyObservers(); // Observer 1 notified of Subject, Observer 2 notified of Subject, Observer 3 notified of Subject

subject.removeObserver(observer2);

subject.notifyObservers(); // Observer 1 notified of Subject, Observer 3 notified of Subject

19. 中介者模式(Mediator Pattern)

中介者模式是一种通过中介对象封装一系列对象之间的交互,从而使对象之间不再相互引用的模式。

function Mediator() {
  this.colleagues = [];
}

Mediator.prototype.addColleague = function(colleague) {
  this.colleagues.push(colleague);
};

Mediator.prototype.send = function(sender, message) {
  for (let i = 0; i < this.colleagues.length; i++) {
    if (this.colleagues[i] !== sender) {
      this.colleagues[i].receive(message);
    }
  }
};

function Colleague(mediator) {
  this.mediator = mediator;
}

Colleague.prototype.send = function(message) {
  this.mediator.send(this, message);
};

Colleague.prototype.receive = function(message) {
  console.log("Received message: " + message);
};

const mediator = new Mediator();
const colleague1 = new Colleague(mediator);
const colleague2 = new Colleague(mediator);

mediator.addColleague(colleague1);
mediator.addColleague(colleague2);

colleague1.send("Hello");
colleague2.send("Hi");

20. 备忘录模式(Memento Pattern)

备忘录模式是一种在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态的模式。

function Memento(state) {
  this.state = state;
}

function Originator() {
  this.state = null;
}

Originator.prototype.setState = function(state) {
  this.state = state;
};

Originator.prototype.getState = function() {
  return this.state;
};

Originator.prototype.saveStateToMemento = function() {
  return new Memento(this.state);
};

Originator.prototype.getStateFromMemento = function(memento) {
  this.state = memento.state;
};

function CareTaker() {
  this.mementos = [];
}

CareTaker.prototype.add = function(memento) {
  this.mementos.push(memento);
};

CareTaker.prototype.get = function(index) {
  return this.mementos[index];
};

const originator = new Originator();
const careTaker = new CareTaker();

originator.setState("State 1");
originator.setState("State 2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State 3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State 4");

console.log("Current state: " + originator.getState());
originator.getStateFromMemento(careTaker.get(0));
console.log("First saved state: " + originator.getState());
originator.getStateFromMemento(careTaker.get(1));
console.log("Second saved state: " + originator.getState());

21. 解释器模式(Interpreter Pattern)

解释器模式是一种定义语言的文法,并且建立一个解释器来解释该语言中的句子的模式。

function Context(input) {
  this.input = input;
  this.output = 0;
}

function Expression() {}

Expression.prototype.interpret = function(context) {
  throw new Error("Not implemented");
};

function TerminalExpression(symbol) {
  this.symbol = symbol;
}

TerminalExpression.prototype = Object.create(Expression.prototype);
TerminalExpression.prototype.constructor = TerminalExpression;

TerminalExpression.prototype.interpret = function(context) {
  if (context.input.startsWith(this.symbol)) {
    context.output += 4;
    context.input = context.input.slice(1);
  }
};

function NonterminalExpression() {
  this.expressions = [];
}

NonterminalExpression.prototype = Object.create(Expression.prototype);
NonterminalExpression.prototype.constructor = NonterminalExpression;

NonterminalExpression.prototype.interpret = function(context) {
  while (context.input.length > 0) {
    const symbol = context.input[0];
    if (symbol === "I") {
      const expression = new TerminalExpression("I");
      expression.interpret(context);
      this.expressions.push(expression);
    } else if (symbol === "V") {
      const expression = new TerminalExpression("V");
      expression.interpret(context);
      this.expressions.push(expression);
    } else if (symbol === "X") {
      const expression = new TerminalExpression("X");
      expression.interpret(context);
      this.expressions.push(expression);
    } else {
      break;
    }
  }

  let result = 0;
  for (let i = 0; i < this.expressions.length; i++) {
    result += this.expressions[i].interpret(context);
  }
  context.output = result;
};

const context = new Context("XXXIV");
const expression = new NonterminalExpression();
expression.interpret(context);
console.log(context.output); // 34

22.订阅-发布模式(Publish-Subscribe Pattern)

订阅-发布模式是一种在对象之间定义一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知的模式。

function PubSub() {
  this.topics = {};
}

PubSub.prototype.subscribe = function(topic, callback) {
  if (!this.topics[topic]) {
    this.topics[topic] = [];
  }
  this.topics[topic].push(callback);
};

PubSub.prototype.publish = function(topic, data) {
  if (!this.topics[topic]) {
    return;
  }
  this.topics[topic].forEach(function(callback) {
    callback(data);
  });
};

const pubSub = new PubSub();

const subscription1 = pubSub.subscribe("topic1", function(data) {
  console.log("Subscription 1 received data: " + data);
});

const subscription2 = pubSub.subscribe("topic2", function(data) {
  console.log("Subscription 2 received data: " + data);
});

pubSub.publish("topic1", "Hello, topic 1 subscribers!");
pubSub.publish("topic2", "Hi, topic 2 subscribers!");

pubSub.subscribe("topic1", function(data) {
  console.log("Subscription 3 received data: " + data);
});

pubSub.publish("topic1", "Hello again, topic 1 subscribers!");

pubSub.unsubscribe("topic1", subscription1);

pubSub.publish("topic1", "Hello, topic 1 subscribers!"); // Only subscription 3 will receive this message

23.责任链模式(Chain of Responsibility Pattern)

责任链模式是一种将请求沿着处理者链进行传递,直到有一个处理者处理该请求的模式。这种模式可以将请求发送者和接收者解耦。

function Handler() {
  this.nextHandler = null;
}

Handler.prototype.setNextHandler = function(handler) {
  this.nextHandler = handler;
};

Handler.prototype.handleRequest = function(request) {
  if (this.nextHandler) {
    this.nextHandler.handleRequest(request);
  }
};

function ConcreteHandler1() {}

ConcreteHandler1.prototype = Object.create(Handler.prototype);
ConcreteHandler1.prototype.constructor = ConcreteHandler1;

ConcreteHandler1.prototype.handleRequest = function(request) {
  if (request === "Request 1") {
    console.log("Concrete handler 1 handles the request");
  } else {
    Handler.prototype.handleRequest.call(this, request);
  }
};

function ConcreteHandler2() {}

ConcreteHandler2.prototype = Object.create(Handler.prototype);
ConcreteHandler2.prototype.constructor = ConcreteHandler2;

ConcreteHandler2.prototype.handleRequest = function(request) {
  if (request === "Request 2") {
    console.log("Concrete handler 2 handles the request");
  } else {
    Handler.prototype.handleRequest.call(this, request);
  }
};

const handler1 = new ConcreteHandler1();
const handler2 = new ConcreteHandler2();

handler1.setNextHandler(handler2);

handler1.handleRequest("Request 1"); // Concrete handler 1 handles the request
handler1.handleRequest("Request 2"); // Concrete handler 2 handles the request
handler1.handleRequest("Request 3"); // Request not handled