15 C++设计模式之命令(Command)模式

命令(Command)模式定义

命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

命令(Command)模式优缺点

优点
  • 它能较容易的设计一个命令队列;
  • 在需要的情况下,可以较容易的将命令计入日志;
  • 允许接收请求的一方决定是否要否决请求;
  • 可以容易的实现对请求的撤销和重做;
  • 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;
  • 把请求一个操作的对象与知道怎么执行一个操作的对象分隔开;
缺点
  • 代码可能会变得更加复杂,因为你在发送者和接收者之间增 加了一个全新的层次

命令(Command)模式构成与实现

构成
  • 发送者(Sender)——亦称“触发者(Invoker)”——类负责对请求进行初始化,其中必须包含一个成员变量来存储对于命令对象的引用。发送者触发命令,而不向接收者直接发送请求。注意,发送者并不负责创建命令对象:它通常会通过构造函数从客户端处获得预先生成的命令。
  • 命令(Command)接口通常仅声明一个执行命令的方法。
  • 具体命令(Concrete Commands)会实现各种类型的请求。具体命令自身并不完成工作,而是会将调用委派给一个业务逻辑对象。但为了简化代码,这些类可以进行合并。接收对象执行方法所需的参数可以声明为具体命令的成员变量。你可以将命令对象设为不可变,仅允许通过构造函数对这些成员变量进行初始化。
  • 接收者(Receiver)类包含部分业务逻辑。几乎任何对象都可以作为接收者。绝大部分命令只处理如何将请求传递到接收者的细节,接收者自己会完成实际的工作。
  • 客户端(Client)会创建并配置具体命令对象。客户端必须将包括接收者实体在内的所有请求参数传递给命令的构造函数。此后,生成的命令就可以与一个或多个发送者相关联了。
实例

Command.h:

#ifndef COMMAND_H_
#define COMMAND_H_

// 命令接口, C++中为抽象基类
class Command {
 public:
    virtual void execute() = 0;
};

#endif  // COMMAND_H_

Receiver.h:

#ifndef RECEIVER_H_
#define RECEIVER_H_

#include <iostream>

// 接受者: 电视
class Television{
 public:
    void open() {
        std::cout << "打开电视机!" << std::endl;
    }

    void close() {
        std::cout << "关闭电视机!" << std::endl;
    }

    void changeChannel(){
        std::cout << "切换电视频道!" << std::endl;
    }
};

#endif  // RECEIVER_H_

ConcreteCommand.h:

#ifndef CONCRETE_COMMAND_H_
#define CONCRETE_COMMAND_H_

#include <memory>
#include "Command.h"
#include "Receiver.h"

// 具体命令类: 打开电视
class TVOpenCommand : public Command{
 public:
    explicit TVOpenCommand(std::shared_ptr<Television> tv) : tv_(tv) {}

    void execute() {
        tv_->open();
    }

 private:
    std::shared_ptr<Television> tv_;
};

// 具体命令类: 关闭电视
class TVCloseCommand : public Command{
 public:
    explicit TVCloseCommand(std::shared_ptr<Television> tv) : tv_(tv) {}

    void execute() {
        tv_->close();
    }

 private:
    std::shared_ptr<Television> tv_;
};


// 具体命令类: 切换频道
class TVChangeCommand : public Command{
 public:
    explicit TVChangeCommand(std::shared_ptr<Television> tv) : tv_(tv) {}
    void execute() {
        tv_->changeChannel();
    }

 private:
    std::shared_ptr<Television> tv_;
};

#endif  // CONCRETE_COMMAND_H_

Invoker.h:

#ifndef INVOKER_H_
#define INVOKER_H_

#include <memory>
#include "Command.h"

// 触发者: 遥控器
class Controller{
 public:
    Controller() {}
    // 设置命令
    void setCommand(std::shared_ptr<Command> cmd) {
        cmd_ = cmd;
    }
    // 执行命令
    void executeCommand() {
        cmd_->execute();
    }

 private:
    std::shared_ptr<Command> cmd_;
};

#endif  // INVOKER_H_

main.cpp:

#include "Invoker.h"
#include "ConcreteCommand.h"

int main() {

    system("chcp 65001");
    // 接收者: 电视机
    std::shared_ptr<Television> tv = std::make_shared<Television>();

    // 命令
    std::shared_ptr<Command> openCommand = std::make_shared<TVOpenCommand>(tv);
    std::shared_ptr<Command> closeCommand = std::make_shared<TVCloseCommand>(tv);
    std::shared_ptr<Command> changeCommand = std::make_shared<TVChangeCommand>(tv);

    // 调用者: 遥控器
    std::shared_ptr<Controller> controller = std::make_shared<Controller>();

    // 测试
    controller->setCommand(openCommand);
    controller->executeCommand();
    controller->setCommand(closeCommand);
    controller->executeCommand();
    controller->setCommand(changeCommand);
    controller->executeCommand();
    system("pause");
}

输出:

Active code page: 65001
打开电视机!
关闭电视机!
切换电视频道!
Press any key to continue . . .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Carson.Yang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值