策略模型类的行为模式

策略模式:核心思想是在运行时基于场景抉择策略。
上面,咱们能够通过一个红绿灯程序来看一下这一概念的实现。在这个例子中,咱们能够看到 交通管制(TrafficControl)就决定了运行时环境的上下文,它能够通过转换( turn )这个办法来切换不同的策略。红绿灯(TrafficLight)是一个抽象类的策略,它能够依据环境须要,延长出具体类的策略。

// encapsulationclass TrafficControl {  turn(trafficlight) {    return trafficlight.trafficcolor();  }}class TrafficLight {  trafficcolor() {    return this.colorDesc;  }}// strategy 1class RedLight extends TrafficLight {  constructor() {    super();    this.colorDesc = "Stop";  }}// strategy 2class YellowLight extends TrafficLight {  constructor() {    super();    this.colorDesc = "Wait";  }}// strategy 3class GreenLight extends TrafficLight {  constructor() {    super();    this.colorDesc = "Go";  }}// usagevar trafficControl = new TrafficControl();console.log(trafficControl.turn(new RedLight())); // Stopconsole.log(trafficControl.turn(new YellowLight())); // Waitconsole.log(trafficControl.turn(new GreenLight())); // Go

状态模式:它的外围概念是依据运行时状态的不同,切换不同的策略。算是策略模式的一个延长。
酒店预约的订单状态例子:

同样,咱们能够通过讲策略模式时的红绿灯案例做一些革新,退出状态 state,看看会产生什么。这里,咱们能够看到每次当咱们执行 turn 在做切换的时候,随着状态在红、黄、绿三种状态之间循环更新,红绿灯的批示也跟着更新。

class TrafficControl {  constructor() {    this.states = [new GreenLight(), new RedLight(), new YellowLight()];    this.current = this.states[0];  }  turn() {    const totalStates = this.states.length;    let currentIndex = this.states.findIndex(light => light === this.current);    if (currentIndex + 1 < totalStates) this.current = this.states[currentIndex + 1];    else this.current = this.states[0];  }  desc() {    return this.current.desc();  }}class TrafficLight {  constructor(light) {    this.light = light;  }}class RedLight extends TrafficLight {  constructor() {    super('red');  }  desc() {    return 'Stop';  }}class YellowLight extends TrafficLight {  constructor() {    super('yellow');  }  desc() {    return 'Wait';  }}class GreenLight extends TrafficLight {  constructor() {    super('green');  }  desc() {    return 'Go';  }}// usagevar trafficControl = new TrafficControl();console.log(trafficControl.desc()); // 'Go'trafficControl.turn();console.log(trafficControl.desc()); // 'Stop'trafficControl.turn();console.log(trafficControl.desc()); // 'Wait'

模版模式:它的核心思想是在一个办法中定义一个业务逻辑模版,并将某些步骤推延到子类中实现。所以它和策略模式有些相似。

上面咱们能够看一个实现的例子。在这个例子里,咱们看到员工 employee 里的工作 work 就是一个模版,它外面的工作 tasks 是提早到开发 developer 和设计 designer 两个子类中去实现的。这就是一个简略的模版模式的设计实现。

class Employee {  constructor(name, salary) {  this.name = name;  this.salary = salary;  }  work() {    return `${this.name}负责${this.tasks()}`;  }  getPaid() {    return `${this.name}薪资是${this.salary}`;  }}class Developer extends Employee {  constructor(name, salary) {    super(name, salary);  }  // 细节由子类实现  tasks() {    return '写代码';  }}class Designer extends Employee {  constructor(name, salary) {    super(name, salary);  }  // 细节由子类实现  tasks() {    return '做设计';  }}// usagevar dev = new Developer('张三', 10000);console.log(dev.getPaid()); // '张三薪资是10000'console.log(dev.work()); // '张三负责写代码'var designer = new Designer('李四', 11000);console.log(designer.getPaid()); // '李四薪资是11000'console.log(designer.work()); // '李四负责做设计'

无论是策略、状态还是模版模式,它们都是基于某种“策略模型”来实现的。比方策略模式中的策略是基于上行文来切换;在状态模式中是依据状态来做切换;而最初在模版模式的例子中,某些策略模版在父类中定义,有些则在子类中实现。

信息传递类的行为模式

中介模式:外围是使组件能够通过一个中心点互相交互。
现实生活中,航空高空塔台就是一个例子,咱们不可能让飞机之间交谈,而是通过高空控制台协调。高空塔台人员须要确保所有飞机都接管到平安航行所需的信息,而不会撞到其余飞机。

看一下代码的示例,塔台(TrafficTower)有着接管每架飞机坐标和获取某架飞机坐标办法。同时,飞机会注销本人的坐标和获取其它飞机的坐标。这些信息都是对立由塔台(TrafficTower)来治理的。

class TrafficTower {  #airplanes;  constructor() {    this.#airplanes = [];  }  register(airplane) {    this.#airplanes.push(airplane);    airplane.register(this);  }  requestCoordinates(airplane) {    return this.#airplanes.filter(plane => airplane !== plane).map(plane => plane.coordinates);  }}class Airplane {  constructor(coordinates) {    this.coordinates = coordinates;    this.trafficTower = null;  }  register(trafficTower) {    this.trafficTower = trafficTower;  }  requestCoordinates() {    if (this.trafficTower) return this.trafficTower.requestCoordinates(this);    return null;  }}// usagevar tower = new TrafficTower();var airplanes = [new Airplane(10), new Airplane(20), new Airplane(30)];airplanes.forEach(airplane => {  tower.register(airplane);});console.log(airplanes.map(airplane => airplane.requestCoordinates())) // [[20, 30], [10, 30], [10, 20]]

命令模式:容许咱们将命令和发动命令操作的对象拆散,这么做的益处是对于解决具备特定生命周期或者列队执行的命令,它会给咱们更多的控制权。并且它还提供了将办法调用作为传参的能力,这样做的益处是能够让办法按需执行。

举个例子,事务管理者 OperationManager 接到了执行工作,会依据不同的命令,如启动口头(StartOperationCommand)、追踪口头状态(TrackOperationCommand)及勾销口头 CancelOperationCommand 等来执行。

class OperationManager {  constructor() {    this.operations = [];  }  execute(command, ...args) {    return command.execute(this.operations, ...args);  }}class Command {  constructor(execute) {    this.execute = execute;  }}function StartOperationCommand(operation, id) {  return new Command(operations => {    operations.push(id);    console.log(`你胜利的启动了${operation}口头,代号${id}`);  });}function CancelOperationCommand(id) {  return new Command(operations => {    operations = operations.filter(operation => operation.id !== id);    console.log(`你勾销了行动代号${id}`);  });}function TrackOperationCommand(id) {  return new Command(() =>    console.log(`你的行动代号${id},目前正在执行中`)  );}var manager = new OperationManager();manager.execute(new StartOperationCommand("猎豹", "318"));// 返回:你胜利的启动了猎豹口头,代号318manager.execute(new TrackOperationCommand("318"));// 返回:你的行动代号318,目前正在执行中manager.execute(new CancelOperationCommand("318"));// 返回:你勾销了行动代号318

命令模式能够在许多不同的状况下应用,特地是在创立重交互的 UI 上,比方编辑器里吊销的操作,因为它能够让 UI 对象和行为操作做到高度解耦。也能够用来代替回调函数,这也是因为它更反对模块化地将行为操作在对象之间传递。
职责链模式:外围是将申请的发送者和接收者解耦。
它的实现是通过一个对象链,链中的每个对象都能够解决申请或将其传递给下一个对象。
事件的捕捉和冒泡就是采纳这种形式;jQuery也是职责链每次返回一个对象来实现链式调用。

简略示例:

class CumulativeSum {  constructor(intialValue = 0) {    this.sum = intialValue;  }  add(value) {    this.sum += value;    return this;  }}// usagevar sum = new CumulativeSum();console.log(sum.add(10).add(2).add(50).sum); // 62

中介模式中,咱们须要在网状的环境中,信息对多个对象中通过中介进行传输;命令模式中,咱们看到了信息在对象和对象之间的传输;而最初,在职责链的模式中,咱们又看到了信息在一个流水线中的传输。因而我说它们是偏差“数据传递”的设计模式。

此文章为2月Day5学习笔记,内容来源于极客工夫《Jvascript进阶实战课》,大家共同进步