《完美设计模式》之命令模式

命令模式(Command Pattern)

将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。对请求排队或记录请求日志,以支持可撤销的操作

主要解决:

在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。
何时使用:在某些场合,比如要对行为进行”记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将”行为请求者”与”行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
如何解决:通过调用者调用接受者执行命令,顺序:调用者→接受者→命令。
关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口

应用实例:

struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的Command。

优点:

1、降低了系统耦合度。
2、新的命令可以很容易添加到系统中去。
3、系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,可以使用命令模式

缺点:

使用命令模式可能会导致某些系统有过多的具体命令类。

使用场景:

认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。

实例

在上学那会, 班长一般都充当了学生和老师之间的桥梁,什么时候上课由班长来通知,作业也由班长来通知, 但是真正的执行者是老师,上课是老师决定的,下课是老师决定的,班长其一个通知的作用,这相当与于一个一个的命令,由班长传达, 老师执行, 下面我们就通过了命令模式实现了这个过程。

#include <iostream>
#include "commandmode.h"

int main(int argc, char *argv[])
{
    //老师
    Teacher *teacher = new Teacher;
    //定义老师可执行的事务
    Command *attendClass = new AttendClassCommand(teacher);
    Command *finishClass = new FinishClassCommand(teacher);
    Command *receiverHomework = new ReceiverHomework(teacher);
    //班长
    Monitor *monitor = new Monitor;
    //给班长增加职责
    monitor->addCommand(attendClass);
    monitor->addCommand(finishClass);
    monitor->addCommand(receiverHomework);
    monitor->undoCommand(finishClass);
    //班长通知后, 老师开始执行
    monitor->notify();

    return 0;
}
#ifndef COMMANDMODE_H
#define COMMANDMODE_H
#include <iostream>
#include <list>
#include <iterator>
using namespace std;
using std::cout;
using std::endl;

class Teacher
{
public:
    Teacher(){}

    /**
     * @brief attendClass
     * 执行上课这个行为
     */
    void attendClass()
    {
        cout << "Teacher: attend class now" << endl;
    }
    /**
     * @brief finseClass
     * 时间到,老师执行下课这个行为
     */
    void finishClass()
    {
        cout << "Teacher: finsh class now"  << endl;
    }
    /**
     * @brief receiverHomework
     * 老师,收家庭作业
     */
    void receiverHomework()
    {
        cout << "Teacher: receiver homework now" << endl;
    }
};

/**
 * @brief The Command class
 * 所有的具体命令都实现Commmand这个抽象类,其中命令和命令的执行者是依赖的关系
 * Teacher 是命令的执行者
 */
class Teacher;
class Command
{
public:
    Command(Teacher *teacher): teacher(teacher){}
    virtual void exec(){}

protected:
    Teacher *teacher;
};

class AttendClassCommand : public Command
{
public:
    AttendClassCommand(Teacher *teacher): Command(teacher){}
    void exec()
    {
        teacher->attendClass();
    }
};

class FinishClassCommand : public Command
{
public:
    FinishClassCommand(Teacher *teacher): Command(teacher){}
    void exec()
    {
        teacher->finishClass();
    }
};

class ReceiverHomework : public Command
{
public:
    ReceiverHomework(Teacher *teacher): Command(teacher){}
    void exec()
    {
        teacher->receiverHomework();
    }

};

/**
 * @brief The Monitor class
 * 这个类负起通知作用, 同学上课有班长通知,收作业也是由班长通知
 */
class Monitor
{
public:
    Monitor(){}
    /**
     * @brief Notify
     * 通知执行命令
     */
    void notify()
    {
        for(Command * cmd: commandList)
        {
            cmd->exec();
        }
    }
    /**
     * @brief addCommand
     * @param cmd
     * 增加职责
     */
    void  addCommand(Command *cmd)
    {
        commandList.push_back(cmd);
    }
    /**
     * @brief undoCommand
     * @param cmd
     * 撤销命令
     */
    void undoCommand(Command *cmd)
    {
        for (auto iter=commandList.begin();
             iter!=commandList.end();
             iter++)
        {
            if (*iter == cmd)
            {
                commandList.erase(iter);
                return ; //删除其中一个元素后,迭代器失效
            }
        }
    }

private:
    list<Command *> commandList;

};

#endif // COMMANDMODE_H

运行结果

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值