抽象个Command, Command需要做到执行命令、撤消上次所做的操作及重做, 这里就可以用上面的UndoRedoManager:
abstract class Command implements Executable, UndoRedoable{ constructor(protected controller: Controllable) { } execute(param: {}){ UndoRedoManager.push(this, param); } redo(){ UndoRedoManager.redo(); } undo(){ UndoRedoManager.undo(); } }接下来分别实现具体的 开、关、换台命令:
class OpenCommand extends Command{ execute(param: any){ super.execute(param); this.tv.open(); } undo(currParam: any, lastParam: any){ this.tv.close(); } } class CloseCommand extends Command{ execute(param: any){ super.execute(param); this.tv.close(); } undo(currParam: any, lastParam: any){ this.tv.open(); } } class SwitchCommand extends Command{ execute(param: any){ super.execute(param); this.tv.switchTo(param.channelNum); } undo(currParam: any, lastParam: any){ this.tv.switchTo(lastParam.channelNum); } }最后来实现 电视和遥控器,遥控器通常只有一个开关按钮,要么开要么关,另外遥控器可以撤消到上次选的频道,也可以取消撤消,重新回到当前的:
电视只需要做具体的事就可以了,遥控器也不需要知道命令是谁在执行,只管发命令就好,这就是命令模式的好处。
来看看成果:
先定个执行顺序,
打开电视 -> 3频道 -> 4频道 -> 7频道 -> 撤消 -> 撤消 -> 重做 -> 11频道 -> 12频道 -> 撤消 -> 撤消 -> 关电视
预期结果:
open -> 3 -> 4 -> 7 -> 4 -> 3 -> 4 -> 11 -> 12 -> 11 -> 4 -> close
从11回到4是因为在push 11频道时的command是4,也就是7已经被删掉了。
看看具体执行结果:
let tv = new TV(); let controller = new Controller(new OpenCommand(tv), new CloseCommand(tv), new SwitchCommand(tv)); controller.onOff(); controller.switchTo(3); controller.switchTo(4); controller.switchTo(7); controller.undo(); controller.undo(); controller.redo(); controller.switchTo(11); controller.switchTo(12); controller.undo(); controller.undo(); controller.onOff();执行结果:
open
switch to channel: 3
switch to channel: 4
switch to channel: 7
switch to channel: 4
switch to channel: 3
switch to channel: 4
switch to channel: 11
switch to channel: 12
switch to channel: 11
switch to channel: 4
close
完全一样,没问题。