设计模式之命令模式

概述:

利用饭店的点餐软件案例实现一个命令设计模式,参考资料《大话设计模式》;
此案例结合前面文章简单工厂模式;
在软件系统中,“ 行为请求者”与“ 行为实现者”通常呈现一种“ 紧耦合”。但在 某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将 一组行为抽象为对象, 实现二者之间的松耦合。这就是 命令模式(Command Pattern)。

命令模式分析:

1.命令模式的本质是 对命令进行封装,将发出命令的责任和执行命令的责任分割开。
2.每一个命令都是一个操作: 请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。
3.命令模式允许请求的一方和接收的一方独立开来, 使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
4.命令模式使 请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。
5.命令模式的关键在于 引入了抽象命令接口,且 发送者针对抽象命令接口编程,只有实现了抽象命令接口的 具体命令才能与接收者相关联。

模式优点:

1.降低对象之间的耦合度。
2.新的命令可以很容易地加入到系统中。
3.可以比较容易地设计一个组合命令。
4.调用同一方法实现不同的功能

工程结构说明:

在这里插入图片描述
简单说明:
执行具体命令类都继承自命令类,所以才用到了工厂模式,客户点什么了才去对应执行相应命令

界面类代码:

.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QDateTime>
#include <QFile>
#include <QDir>
#include <QMap>
#include <QDebug>
#include "BarbecueFactor.h"
#include "Command.h"
#include "Waiter.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    /**
     * @brief on_comboBox_Type_activated    获取当前选中item
     * @param index
     */
    void on_comboBox_Type_activated(int index);

    /**
     * @brief on_pushButton_2_clicked   下单
     */
    void on_pushButton_2_clicked();

private:
    /**
     * @brief initTime  获取本机时间
     */
    void currTime();

    /**
     * @brief initQssFiles  读取qss文件
     */
    void initQssFiles();

    /**
     * @brief loagData  对下单信息进行记录
     * @param number    桌号
     * @param text      串名
     * @param value     串数量
     * @param type      串口味(微辣、辣、麻辣)
     */
    void loagData(const int &number,const int &value,const QString &text,const QString &type);
private:
    Ui::Widget *ui;
    BarbecueFactor* m_BarFactor;
    Command* m_Com;

};

#endif // WIDGET_H

.cpp:

#include "widget.h"
#include "ui_widget.h"


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    currTime();
    initQssFiles();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::currTime()
{
    //获取本机时间
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd");//yyyy.MM.dd hh:mm:ss.zzz ddd
    ui->label_Time->setText(current_date);
}

void Widget::initQssFiles()
{
    QFile file(QString("%1/AM.qss").arg(QDir::currentPath()));
    file.open(QFile::ReadOnly);
    this->setStyleSheet(file.readAll());
    file.close();
}

void Widget::loagData(const int &number, const int &value, const QString &text, const QString &type)
{
    ui->textBrowser->append(QString("%1 : 号餐桌 %2串: %3 口味:%4").arg(number).arg(value).arg(text).arg(type));
}


void Widget::on_comboBox_Type_activated(int index)
{
	//根据选择烧烤的种类不同去创建相应对象指针并返回
	//Command* m_Com; 具体命令类都继承自 命令类
    m_Com = m_BarFactor->getCommandToVirtual(index);
}

void Widget::on_pushButton_2_clicked()
{
    Waiter m_Waiter;
    //通知服务员烧烤种类
    m_Waiter.SetOrder(m_Com);
    //通知服务员下单(桌号、串数量、串名、口味)
    m_Waiter.Notify(ui->comboBox_Num->currentIndex(),ui->lineEdit_Vear->text().toInt(),ui->comboBox_Type->currentText(),ui->comboBox_State->currentText());
    //界面记录
    loagData(ui->comboBox_Num->currentIndex(),ui->lineEdit_Vear->text().toInt(),ui->comboBox_Type->currentText(),ui->comboBox_State->currentText());
}

工厂类:

.h:

#ifndef BARBECUEFACTOR_H
#define BARBECUEFACTOR_H

#include <QObject>

#include "Barbecuer.h"
#include "Command.h"
#include "BakeMuttonCommand.h"
#include "BackChickWingCommand.h"
#include "BackCevapcici.h"
#include "Waiter.h"
#include <QMessageBox>
#include <QString>

class BarbecueFactor
{
public:
    BarbecueFactor();
    ~BarbecueFactor();
private:
    void CallQMessageBox();
public:
    Command* getCommandToVirtual(const int index);
};

#endif // BARBECUEFACTOR_H

.cpp:

#include "BarbecueFactor.h"

BarbecueFactor::BarbecueFactor()
{
}

BarbecueFactor::~BarbecueFactor()
{
}

void BarbecueFactor::CallQMessageBox()
{
    QMessageBox::warning(NULL,"温馨提示","此商品已无,请选择其他商品就餐!");
}

Command *BarbecueFactor::getCommandToVirtual(const int index)
{
    Barbecuer* boy = new Barbecuer;
    Command *m_pCom = NULL;
    switch(index)
    {
    case 1:
        m_pCom = new BakeMuttonCommand(boy);
        break;
    case 2:
        m_pCom = new BackChickWingCommand(boy);
        break;
    case 3:
        m_pCom = new BackCevapcici(boy);
        break;
    default:
        CallQMessageBox();
        break;
    }
    return m_pCom;
}


烤肉实现类:

.h:

#ifndef BARBECUER_H
#define BARBECUER_H

#include <QObject>


class Barbecuer//烤肉串者类
{
public:
    Barbecuer();
    ~Barbecuer();

public:
    //肉串
    void BakeMutton(const int &number, const int &value, const QString &text, const QString &type);
    //鸡翅
    void BakeChicking(const int &number, const int &value, const QString &text, const QString &type);
    //鸡翅
    void BakeCevapcici(const int &number, const int &value, const QString &text, const QString &type);//烤肠

};

#endif // BARBECUER_H

.cpp:


服务员类:

.h:

#ifndef WAITER_H
#define WAITER_H

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

class Waiter
{
public:
    Waiter();
    ~Waiter();

public:
    /**
     * @brief SetOrder  进行命令注册
     * @param command   
     */
    void SetOrder(Command*command);

    /**
     * @brief Notify
     * @param number    桌号
     * @param text      串名
     * @param value     串数量
     * @param type      串口味(微辣、辣、麻辣)
     */
    void Notify(const int &number, const int &value, const QString &text, const QString &type);

private:
    Command* m_pCommand;
};

#endif // WAITER_H

.cpp:

#include "Waiter.h"

Waiter::Waiter()
{
}

Waiter::~Waiter()
{
}

void Waiter::SetOrder(Command *command)
{
    this->m_pCommand = command;
}

void Waiter::Notify(const int &number, const int &value, const QString &text, const QString &type)
{
    m_pCommand->ExcuteCommand(number,value,text,type);

}

执行具体命令类(烤肠):

.h:

#ifndef BACKCEVAPCICI_H
#define BACKCEVAPCICI_H

#include "Command.h"
#include "Barbecuer.h"

class BackCevapcici : public Command
{
public:
    BackCevapcici(Barbecuer* receiver);
    ~BackCevapcici();

    void ExcuteCommand(const int &number, const int &value, const QString &text, const QString &type);

private:
    Barbecuer* m_Barbecuer;
};

#endif // BACKCEVAPCICI_H

.cpp:

#include "BackCevapcici.h"

BackCevapcici::BackCevapcici(Barbecuer* receiver):Command(receiver)
{
    this->m_Barbecuer = receiver;
}

BackCevapcici::~BackCevapcici()
{
}

void BackCevapcici::ExcuteCommand(const int &number, const int &value, const QString &text, const QString &type)
{
    //烤肠类去具体实现
    m_Barbecuer->BakeCevapcici(number,value,text,type);
}

执行具体命令类(烤肉):

.h:

#ifndef BAKEMUTTONCOMMAND_H
#define BAKEMUTTONCOMMAND_H
#include "Command.h"

class BakeMuttonCommand : public Command
{
public:
    BakeMuttonCommand(Barbecuer *receiver);
    ~BakeMuttonCommand();

public:
    void ExcuteCommand(const int &number, const int &value, const QString &text, const QString &type);

private:
    Barbecuer* m_recvier;
};

#endif // BAKEMUTTONCOMMAND_H

.cpp:

#include "BakeMuttonCommand.h"

BakeMuttonCommand::BakeMuttonCommand(Barbecuer* receiver):Command(receiver)
{
    this->m_receiver = receiver;
}

BakeMuttonCommand::~BakeMuttonCommand()
{
}

void BakeMuttonCommand::ExcuteCommand(const int &number, const int &value, const QString &text, const QString &type)
{
    m_receiver->BakeMutton(number,value,text,type);
}

执行具体命令类(烤鸡翅):

.h:

#ifndef BACKCHICKWINGCOMMAND_H
#define BACKCHICKWINGCOMMAND_H

#include <QObject>
#include "Command.h"
#include "Barbecuer.h"

class BackChickWingCommand : public Command
{
public:
    BackChickWingCommand(Barbecuer* receiver);
    ~BackChickWingCommand();

public:
    void ExcuteCommand(const int &number, const int &value, const QString &text, const QString &type);

private:
    Barbecuer* m_pBarbecuer;
};

#endif // BACKCHICKWINGCOMMAND_H

.cpp:

#include "BackChickWingCommand.h"

BackChickWingCommand::BackChickWingCommand(Barbecuer *receiver):Command(receiver)
{
    this->m_receiver = receiver;
}

BackChickWingCommand::~BackChickWingCommand()
{

}

void BackChickWingCommand::ExcuteCommand(const int &number, const int &value, const QString &text, const QString &type)
{
    m_receiver->BakeChicking(number,value,text,type);
}

运行效果图:

在这里插入图片描述
总结:
作者也是边学习便分享,真心希望大家也动手敲一敲,体会C++其中的乐趣,本案例有好多业务逻辑没有填进去,大家如果感兴趣可以和我一起实现一个完整的点餐平台;

over:

欢迎大家关注作者在文末评论、点赞、转发以及批评指正!
如果大家有更好的方法或有问题可以在文末评论一起讨论!
共同学习!
共同进步!

文末一句话:

苏轼说,平淡乃绚烂之极也。
品过人生的苦辣酸甜,淡,是人生最真的滋味。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值