命令模式

一 应用场景
去餐厅点烤羊肉的时候,我们是通过服务员来点菜,具体是谁来做这些菜和他们什么时候完成的这些菜。“我们”是命令发送者,“厨师”是命令接收者者,两者是松耦合的。

在软件开发过程中经常需要向某些对象发送请求(调用其中的某个或某些方法),但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,适合以一种松耦合的方式来设计软件,使得请求发送者与请求接收者能够消除彼此之间的耦合,让对象之间的调用关系更加灵活,可以灵活地指定请求接收者以及被请求的操作。命令模式为此类问题提供了一个较为完美的解决方案。

二 定义
命令模式 Command Pattern:将一个请求封装为一个对象,从而让我们对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。
这里写图片描述
Command 抽象命令类:抽象命令类,声明用于执行请求的execute等方法,通过这些方法可以调用请求接受者的相关操作。

ConcreteCommand 具体命令类:是抽象命令类的子类,实现了抽象命令类中声明的方法。对应具体的接收者对象,将接收者对象的动作绑定在其中。实现execute方法的时候将调用接收者对象的相关操作。

Invoker 调用者:即请求的发送者,通过命令对象来执行请求,一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的execute()方法,从而实现间接调用请求接收者的相关操作。

Receiver 接收者:接收者执行与请求相关的操作,它具体实现对请求的业务处理。

命令模式的本质是对请求进行封装,一个请求对应于一个命令,将发出命令的责任和执行命令的责任分割开。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执行、何时被执行,以及是怎么被执行的。

三 C++实现一个命令模式
Command.h

#pragma once 

#include <iostream>
#include <string>

using namespace std;

class Chef //相当于Receiver
{
public:
    Chef(){};

    virtual ~Chef(){};

    void makeMutton(){
        std::cout << "make mutton" << std::endl;
    }
};

Command.h

#pragma once 

#include <iostream>
#include <string>
#include "Chef.h"

using namespace std;

class Command
{
protected:
    Chef * chef;

public:
    Command(){}

    Command(Chef * _chef){
        chef = _chef;
    }

    virtual void Execute() = 0;

    virtual ~Command(){}
};

MakeMutton.h

#pragma once 

#include <iostream>
#include <string>
#include "Command.h"

using namespace std;

class MakeMutton:public Command //相当于ConcreteCommand
{
private:

public:
    MakeMutton(Chef * _chef){
        chef = _chef;
    }

    void Execute(){
        chef->makeMutton();
    }
};

Waiter.h

#pragma once

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

using namespace std;

class Waiter
{
private:
    std::vector<Command *> command_vector;

public:
    Waiter(){};

    virtual ~Waiter(){}

    void setOrder(Command * _command){
        std::cout << "make a mutton" << std::endl;
        command_vector.push_back(_command);
    }

    void sendOrder(){
        vector<Command *>::iterator it;
        for(it=command_vector.begin();it!=command_vector.end();it++){
            (*it)->Execute();
        }
    }
};

main.cpp

#include <iostream>
#include <string>

#include "Waiter.h"
#include "MakeMutton.h"

int main()
{
    Chef * chef = new Chef();
    Command * make_mutton = new MakeMutton(chef);
    Waiter * waiter = new Waiter();

    waiter->setOrder(make_mutton);

    waiter->sendOrder();

    delete chef;
    chef = NULL;
    delete make_mutton;
    make_mutton = NULL;
    delete waiter;
    waiter = NULL;

    system("pause");
    return 0;
}

执行结果
这里写图片描述

四 总结
优点:
1 它能较容易地设计一个命令队列
2 降低系统的耦合度
3 可以容易地实现对请求的撤销和重做;

缺点:
对每个命令接收者的调用都需要设计一个具体类,所以会生成大量的类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值