【HeadFirst 设计模式】命令模式的C++实现

一、案例背景

A公司想要生产一款万能遥控器:使用本公司遥控器,只需要设置好需要被控制的设备,比如电视,空调,电灯等,便可以实现遥控,从此摆脱找不到遥控器的情况!

其他电器类的代码和实现已经相应的电器公司提供,你的任务是将这些代码融合进遥控器中,以实现遥控器的功能。

二、案例分析

听起来很不错的一个主意,但是怎么实现呢?

看过了那么多的设计模式,我想"针对接口编程,而不是针对实现编程"这条设计原则已经给你留下了些许印象。你可以会说:我们可以设计一个抽象电器接口,让其他电器类继承自这个接口,然后在遥控器类中使用组合,应该就可以解决问题。是的,但是你忽略了一个问题,电器类的代码已经由各大厂商给出,我们并不能随意修改这些代码。

这种情形下,命令模式也许能解决你的问题。该模式可以使"发出命令"和"执行命令"解耦,发出命令的人只管发出命令而不必关注执行者是怎么完成命令的。想像以下你走进一家餐厅的时候,是不是也只需要看着菜单点菜(下发命令)就行了,而后厨的王牌厨师们也根本不需要关注是谁点了这道西红柿炒蛋,你们不也是已经实现解耦了吗?

三、代码案例

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>
#include <array>

using namespace std;

class Command
{
public:
    virtual void execute() const = 0;
};

class Light
{
public:
    void on() const
    {
        cout << "灯开了..." << endl;
    }
    void off() const
    {
        cout << "灯关了..." << endl;
    }
};

class TV
{
public:
    void on() const
    {
        cout << "电视开了..." << endl;
    }
    void off() const
    {
        cout << "电视关了..." << endl;
    }
};

class AC
{
public:
    void on() const
    {
        cout << "空调开了..." << endl;
    }
    void off() const
    {
        cout << "空调关了..." << endl;
    }
};

class LightOnCommand : public Command
{
private:
    Light& light;

public:
    LightOnCommand(Light& light) : light(light) {}
    void execute() const override
    {
        light.on();
    }
};

class LightOffCommand : public Command
{
private:
    Light& light;

public:
    LightOffCommand(Light& light) : light(light) {}
    void execute() const override
    {
        light.off();
    }
};

class TVOnCommand : public Command
{
private:
    TV& tv;

public:
    TVOnCommand(TV& tv) : tv(tv) {}
    void execute() const override
    {
        tv.on();
    }
};

class TVOffCommand : public Command
{
private:
    TV& tv;

public:
    TVOffCommand(TV& tv) : tv(tv) {}
    void execute() const override
    {
        tv.off();
    }
};

class ACOnCommand : public Command
{
private:
    AC& ac;

public:
    ACOnCommand(AC& ac) : ac(ac) {}
    void execute() const override
    {
        ac.on();
    }
};

class ACOffCommand : public Command
{
private:
    AC& ac;

public:
    ACOffCommand(AC& ac) : ac(ac) {}
    void execute() const override
    {
        ac.off();
    }
};

class Remote
{
private:
    const static int              MAX_SLOT_SUM = 7;
    array<Command*, MAX_SLOT_SUM> onCommand {};
    array<Command*, MAX_SLOT_SUM> offCommand {};

    void execute(const int slot, array<Command*, MAX_SLOT_SUM>& command)
    {
        if (slot < MAX_SLOT_SUM)
        {
            if (command[slot])
            {
                command[slot]->execute();
            }
            else
            {
                std::cout << "slot " << slot << " is empty" << std::endl;
            }
        }
    }

public:
    Remote() {}

    void set(int slot, Command& on, Command& off)
    {
        if (slot < MAX_SLOT_SUM)
        {
            onCommand[slot]  = &on;
            offCommand[slot] = &off;
        }
    }

    void pressOnButton(const int slot)
    {
        execute(slot, onCommand);
    }

    void pressOffButton(const int slot)
    {
        execute(slot, offCommand);
    }
};

enum
{
    _TV,
    _Light,
    _AC
};

int main()
{
    Remote remote;

    TV           tv {};
    TVOnCommand  tvOnCommand(tv);
    TVOffCommand tvOffCommand(tv);
    remote.set(_TV, tvOnCommand, tvOffCommand);

    Light           light {};
    LightOnCommand  lightOnCommand(light);
    LightOffCommand lightOffCommand(light);
    remote.set(_Light, lightOnCommand, lightOffCommand);

    AC           ac {};
    ACOnCommand  acOnCommand(ac);
    ACOffCommand acOffCommand(ac);
    remote.set(_AC, acOnCommand, acOffCommand);

    remote.pressOnButton(0);
    remote.pressOnButton(1);
    remote.pressOnButton(2);
    cout << endl << endl;
    remote.pressOffButton(0);
    remote.pressOffButton(1);
    remote.pressOffButton(2);
    return 0;
}
相关推荐
小龙报21 小时前
【C语言】内存里的 “数字变形记”:整数三码、大小端与浮点数存储真相
c语言·开发语言·c++·创业创新·学习方法·visual studio
刃神太酷啦21 小时前
扒透 STL 底层!map/set 如何封装红黑树?迭代器逻辑 + 键值限制全手撕----《Hello C++ Wrold!》(23)--(C/C++)
java·c语言·javascript·数据结构·c++·算法·leetcode
2301_7890156221 小时前
C++:继承
c语言·开发语言·c++
星河耀银海21 小时前
C++ 运算符重载:自定义类型的运算扩展
android·java·c++
feng_blog66881 天前
C++线程池|解决死锁、崩溃、丢任务所有痛点
java·开发语言·c++
yuanyuan2o21 天前
从最小项目开始的 CMake 教程
c语言·开发语言·arm开发·c++·makefile·make·cmake
xh didida1 天前
算法 -- 位运算
开发语言·c++·算法
hele_two1 天前
VS Code + CMake 调用 SDL2 & SDL2_image 完整编译教程(Windows 平台)
c++·windows·vscode·图形渲染
量子炒饭大师1 天前
【优化算法】双指针算法的「义体化」重构 ——【双指针】双指针算法中的指针是如何定义的?如何使用它进行一些简单的算法?
c++·算法·重构·优化算法·双指针
身如柳絮随风扬1 天前
MyBatis 与 Spring 中的设计模式
spring·设计模式·mybatis