⑥封装调用-命令模式

解耦调用者和请求者

现在有 2 个开关需要控制 2 台设备的开机和停止。设备的开机和停止是一个繁琐的过程,需要设置一些参数,并经历几步操作。

如果我们把对机器的操作都写在开关的实现中,一旦开关流程改变或是更换了设备,都需要重新修改开关的代码。

所以我们考虑先把设备的开机和停止过程封装在一个对象方法里面,开关只要直接调用这个对象的方法就能实现设备开始和停止,不需要关心实现的细节。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface ICommand {
execute(): void;
}

class Device1 implements ICommand {
setOption() {}
step1() {}
step2() {}
on() {}
execute() {
this.setOption();
this.step1();
this.step2();
this.on();
console.log("设备已经开启");
}
}

开关类接受命令类,并直接调用命令类的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ControlA {
command: ICommand;
constructor(command: ICommand) {
this.command = command;
}
setCommand(command: ICommand) {
this.command = command;
}
on() {
this.command.execute();
}
}

const controlA = new ControlA(new Device1());
controlA.on();

对于某些按钮,可能没有实现 execute 方法,而我们又不想通过 ifelse 判断破坏代码风格,可以使用占位符类。

1
2
3
4
5
6
class NoCommand implements ICommand {
execute() {}
}

const controlB = new ControlA(new NoCommand());
controlB.on();

命令模式

将请求封装成对象,以便使用不同的请求,队列,或日志来参数化其他的对象,命令模式也支持可撤销的操作。

宏命令

把所有的命令对象通过一个类编排起来,统一执行,就实现了宏命令

1
2
3
4
5
6
7
8
9
10
11
class MacroCommand implements ICommand {
commandStack: ICommand[] = [];
setCommand(command: ICommand) {
this.commandStack.push(command);
}
execute(): void {
for (let i = 0; i < this.commandStack.length; i++) {
this.commandStack[i].execute();
}
}
}
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2025 SunZhiqi

此时无声胜有声!

支付宝
微信