设计模式1-命令模式

5次阅读

共计 2075 个字符,预计需要花费 6 分钟才能阅读完成。

1. 命令模式介绍

1.1 定义

命令模式的英文翻译是 Command Design Pattern。在 GoF 的《设计模式》一书中,它是这么定义的:

The command pattern encapsulates a request as an object, thereby letting us parameterize other objects with different requests, queue or log requests, and support undoable operations.

  • 中文翻译为:

命令模式:将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。

  • 命令模式的本质:封装请求
  • 设计意图:命令模式通过将请求封装到一个命令 (Command) 对象中,实现了请求调用者和具体实现者之间的解耦。

1.2 应用场景

在需要事务的系统中,可以选用命令模式。命令模式提供了对事务进行建模的方法。命令模式有一个别名就是 Transaction。
命令模式,类似于 C 语言里的回调函数。

1.3 命令模式的结构


命令模式涉及的角色及其职责如下:

  1. 抽象命令(Command):一般定义为接口,用来定义执行命令的接口。
  2. 具体命令 (ConcreteCommand) 角色:通常会持有接收者对象,并调用接收者对象的相应功能来完成命令要执行的操作。
  3. 接收者 (Receiver) 角色:真正执行命令的对象。任何类都可能成为接收者,只要它能够实现命令要求实现的相应功能。
  4. 调用者 (Invoker) 角色:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
  5. 客户端 (Client) 角色:创建具体的命令对象,并且设置命令对象的接收者。

2. 示例代码

以客人点餐为例,实现:点餐和 cook 隔离。

// CommandModel.h 文件
#pragma once
#include <iostream>
#include <vector>
#include <algorithm>

// 烤肉师傅
class BarbecueMaster
{
public:
    void MakeMutton()
    {std::cout << "烤羊腿喽" << std::endl;}
    void MakeChiken()
    {std::cout << "烤鸡肉喽" << std::endl;}
};
// 命令类
class Command
{
protected:
    BarbecueMaster * m_master;
public:
    Command(BarbecueMaster * p)
    {m_master = p;}
    virtual void executeCmd() = 0;};

// 命令 1
class CommandMutton : public Command
{
public:
    CommandMutton(BarbecueMaster * p) : Command(p) {}
    void executeCmd()
    {m_master->MakeMutton();
    }
};

// 命令 2
class CommandChiken : public Command
{
public:
    CommandChiken(BarbecueMaster * p) : Command(p) {}
    void executeCmd()
    {m_master->MakeChiken();
    }
};

// 服务员
class Waiter
{
private:
    std::vector<Command *> m_vec;
public:
    ~Waiter()
    {for (auto it = m_vec.begin(); it != m_vec.end(); it++)
        {delete(*it);
        }
        m_vec.clear();}
    
    // Waiter Func1
    void add(Command * p)
    {m_vec.push_back(p);
    }
    
    // Waiter Func2
    void remove(Command * p)
    {auto it = find(m_vec.begin(), m_vec.end(), p);
        if (it != m_vec.end())
            m_vec.erase(it);
    }
    
    // Waiter Func3
    void submitCmd()
    {for (auto it = m_vec.cbegin(); it != m_vec.cend(); it++)
        {(*it)->executeCmd();}
    }
};

测试代码:

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

int main()
{
    using namespace std;
    // 命令模式
    Waiter * pWaiter = new Waiter();
    BarbecueMaster * pMaster = new BarbecueMaster();
    
    pWaiter->add(new CommandChiken(pMaster));
    pWaiter->add(new CommandMutton(pMaster));
    
    pWaiter->submitCmd();
    
    delete pMaster;
    delete pWaiter;

    getchar();
    return 0;
}
正文完
 0