行为型模式之 命令模式

命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。

主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

如何解决:通过调用者调用接受者执行命令,顺序:调用者→接受者→命令。

关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口

优点: 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。

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

模式动机

在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。

命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。这就是命令模式的模式动机。

实现

我们首先创建作为命令的接口 Order,然后创建作为请求的 Stock 类。实体命令类 BuyStock 和 SellStock,实现了 Order 接口,将执行实际的命令处理。创建作为调用对象的类 Broker,它接受订单并能下订单。

Broker 对象使用命令模式,基于命令的类型确定哪个对象执行哪个命令。CommandPatternDemo,我们的演示类使用 Broker类来演示命令模式。

 

//步骤一 创建一个命令接口
class Order {
public:
    virtual void execute() {}
};

//步骤二 创建一个请求类
class Stock {
private:
    string name = "ABC";
    int quantity = 10;
public:
    void Buy() {
        printf("Buy Stock Name = %s, Quantity = %d",name.c_str(),quantity);
    }
    void Sell() {
        printf("Sell Stock Name = %s, Quantity = %d", name.c_str(), quantity);
    }
};

//步骤 3 创建实现了 Order 接口的实体类

class BuyStock : public Order {
private:
    Stock* abcstock;
public:
    BuyStock(Stock* stock)
    {
        abcstock = stock;
    }
    BuyStock() {}
    void execute() {
        abcstock->Buy();
    }
};

class SellStock :public Order {
private:
    Stock * abcstock;
public:
    SellStock(Stock* stock)
    {
        abcstock = stock;
    }
    SellStock() {}
    void execute() {
        abcstock->Sell();
    }
};

//步骤 4 创建命令调用类
class Broker {
private:
    list<Order*> orderlist;
public:
    void takeOrder(Order* ord) { orderlist.push_back(ord); }
    void placeOrders() {
        list<Order*>::iterator ite = orderlist.begin();
        for (; ite != orderlist.end(); ++ite)
        {
            (*ite)->execute();
        }
    }
};

int main() 
{
    Stock stock;
    BuyStock buy(&stock);
    SellStock sell(&stock);

    Broker broker;
    broker.takeOrder(&buy);
    broker.takeOrder(&sell);

    broker.placeOrders();
    return 0;
}

 

posted @ 2018-03-05 10:25  花园小花匠  阅读(258)  评论(0编辑  收藏  举报