「设计模式」命令模式🍉

236 阅读2分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

命令模式的定义

在命令模式下,会将方法调用、请求或操作封装到单一对象中,从而根据不同的请求对客户进行参数化和传递可执行的方法调用。命令模式为我们提供了一种分离职责的手段,职责包括从执行命令的任意地方发布命令以及将该职责转而委托给不同对象。

命令模式中的命令指的是一个执行某些特定事情的指令。命令模式的本质是对这些指令进行封装,将发出命令的责任和执行命令的责任分隔开。

每一个命令都是一个操作:请求方发出请求,要求执行一个操作;接收方收到请求,并执行操作。请求方不需要知道接收方的接口,也不需要知道中间执行的步骤。

命令模式的应用场景

命令模式适用于以下场景:

  • 需要在不同的时间里进行请求,将请求排队执行
  • 有需要支持命令撤销操作的功能业务,也可以使用命令模式
  • 系统需要支持宏命令,即需要将一组操作组合起来

命令模式的优缺点

优点:

  • 将请求方、接收方以及实现操作的命令对象解耦
  • 命令对象 Command 为头等对象,可以被扩展
  • 可将多个命令组合成宏命令
  • 可实现类似撤销操作的功能 缺点:
  • 代码实现起来优点绕,比较抽象

具体实现的代码

// 操控电视的实践代码
var Command = function() {};

// 命令接收者
var TV = function() {
    this.curChannel = 0;
    this.turnOn = function() {
        console.log('the tv is on');
    };
    this.turnOff = function() {
        console.log('the tv is off');
    };
    this.changeChannel = function(channel) {
        this.curChannel = channel;
        console.log('now the tv is ' + this.curChannel);
    }
};

// 开机命令
var CommandOn = function(tv) {
    Command.apply(this);
    this.tv = tv;
    this.execute = function() {
        this.tv.turnOn();
    }
};

// 关机命令
var CommandOff = function(tv) {
    Command.apply(this);
    this.tv = tv;
    this.execute = function() {
        this.tv.turnOff();
    }
};

// 切换频道命令
var CommandChange = function(tv, channel) {
    Command.apply(this);
    this.tv = tv;
    this.channel = channel;
    this.execute = function() {
        this.tv.changeChannel(this.channel);
    };
};

// 遥控器作为调用者
var Control = function(open, close, change) {
    this.open = open;
    this.close = close;
    this.change = change;

    this.turnOn = function () {
        this.open.execute();
    };

    this.turnOff = function () {
        this.close.execute();
    };

    this.changeChannel = function () {
        this.change.execute();
    };
};

// 电视
var tv = new TV();
// 生成各自的命令
var open = new CommandOn(tv);
var close = new CommandOff(tv);
var change = new CommandChange(tv, 2);
// 遥控器
var control = new Control(open, close, change);
control.turnOn();
control.turnOff();
control.changeChannel();