19.设计模式-命令模式

命令模式(Command):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

需求

实现客户在烤肉店买烤肉的过程。

需求分析

  • 用例功能:1.客户下单2.通知厨师制作3.上桌吃饭4.付钱走人
  • 用例实现:只实现1,2步
  • 下单细化:两种品类,鸡翅、羊肉串
  • 动作细化:下单、撤销、修改数量

代码

业务类

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum {
    MUTTON,
    CHICHKENWING,
    COMMANDMAX
} CommandType;
// 厨师
typedef struct Barbecuer {
    void (*bake[COMMANDMAX])();
} Barbecuer;

void BakeMutton() {
    printf("烤羊肉串\n");
}

void BakeChickenWings() {
    printf("烤鸡翅\n");
}

Barbecuer *InitBarbecuer() {
    Barbecuer *obj = (Barbecuer *)malloc(sizeof(Barbecuer));
    obj->bake[MUTTON] = BakeMutton;
    obj->bake[CHICHKENWING] = BakeChickenWings;
    return obj;
}
// 命令类
typedef struct Command {
    Barbecuer *receiver;
    void (*excecute)(struct Command *);
} Command;

typedef struct BakeMuttonCommand {
    Command base;
} BakeMuttonCommand;

void ExcecuteBakeMuttonCommand(Command *obj) {
    obj->receiver->bake[MUTTON]();
}

Command *InitBakeMuttonCommand(Barbecuer *receiver) {
    BakeMuttonCommand *obj = (BakeMuttonCommand *)malloc(sizeof(BakeMuttonCommand));
    obj->base.excecute = ExcecuteBakeMuttonCommand;
    obj->base.receiver = receiver;
    return (Command *)obj;
}

typedef struct BakeChickenWingsCommand {
    Command base;
} BakeChickenWingsCommand;

void ExcecuteBakeChickenWingsCommand(Command *obj) {
    obj->receiver->bake[CHICHKENWING]();
}

Command *InitBakeChickenWingsCommand(Barbecuer *receiver) {
    BakeChickenWingsCommand *obj = (BakeChickenWingsCommand *)malloc(sizeof(BakeChickenWingsCommand));
    obj->base.excecute = ExcecuteBakeChickenWingsCommand;
    obj->base.receiver = receiver;
    return (Command *)obj;
}

typedef Command *(*CreateCommandInterface)(Barbecuer *);

CreateCommandInterface cmdinterface[COMMANDMAX] = {InitBakeMuttonCommand, InitBakeChickenWingsCommand};

typedef struct Order {
    int num;
    Barbecuer *receiver;
} Order;
// 服务员
typedef struct Waiter {
    Order order[COMMANDMAX];
    void (*setOrder)(struct Waiter *, CommandType, int, Barbecuer *);
    void (*notify)(struct Waiter *);
} Waiter;

void WaiterSetOrder(Waiter *obj, CommandType type, int num, Barbecuer *receiver) {
    obj->order[type] = (Order){num, receiver};
}

void WaiterNotify(Waiter *obj) {
    Command *cmd;
    for(int i=0; i<COMMANDMAX; i++) {
        if(obj->order[i].num != 0) {
            printf("%d串:", obj->order[i].num);
            // 1.直接烤
            obj->order[i].receiver->bake[i]();
            // 2.编成命令再烤
            // cmd = cmdinterface[i](obj->order[i].receiver);
            // cmd->excecute(cmd);
            // free(cmd);
        }
    }
}

Waiter *InitWaiter() {
    Waiter *obj = (Waiter *)malloc(sizeof(Waiter));
    obj->setOrder = WaiterSetOrder;
    obj->notify = WaiterNotify;
    memset(obj->order, 0, sizeof(obj->order));
    return obj;
}

客户端

c 复制代码
int main() {
    Barbecuer *boy = InitBarbecuer();
    Waiter *one = InitWaiter();
    // 开放式厨房,可指定厨师@_@
    // 数量为0就表示撤销
    one->setOrder(one, MUTTON, 2, boy);
    one->setOrder(one, MUTTON, 3, boy);
    one->setOrder(one, CHICHKENWING, 4, boy);
    one->notify(one);
    return 0;
}

UML图

总结

  • 命令模式的优点?
    第一,它能较容易地设计一个命令队列;
    第二,在需要的情况下,可以较容易地将命令记入日志;
    第三,允许接收请求的一方决定是否要否决请求;
    第四,可以容易地实现对请求的撤销和重做;
    第五,由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;

有这些优点的原因是命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。

  • 什么场景使用命令模式?
    命令模式支持撤销/恢复操作功能,但你还不清楚是否需要这个功能时,建议不要使用该模式。敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。------《大话设计模式》
相关推荐
Java后端的Ai之路18 小时前
21、Python - 命令模式
开发语言·人工智能·python·命令模式·外观模式
码匠许师傅20 小时前
【设计模式精讲】15.享元模式(Flyweight)
c++·设计模式·享元模式·uml
事圆则缓21 小时前
Android 常用设计模式速查
android·设计模式
码匠许师傅1 天前
【设计模式精讲】14.外观模式(Facade)
c++·设计模式·uml·外观模式
evans在进步2 天前
Java 常用设计模式(二):装饰器、适配器、责任链、模板方法、策略与观察者
java·开发语言·设计模式
码匠许师傅2 天前
【设计模式精讲】13.装饰器模式(Decorator)
c++·设计模式·uml·装饰器模式
evans在进步3 天前
Java 常用设计模式入门:建造者、工厂、单例、外观与代理
java·python·设计模式
Flutter OH3 天前
Flutter OH 卡死冻屏问题定位指南
flutter·命令模式
字节跳动开源3 天前
VisActor全新图可视化开源项目:VGraph
前端·设计模式·开源
码匠许师傅3 天前
【设计模式精讲】11.桥接模式(Bridge)
c++·设计模式·桥接模式·uml