命令模式
概述:
利用饭店的点餐软件案例实现一个命令设计模式,参考资料《大话设计模式》;
此案例结合前面文章简单工厂模式;
在软件系统中,“ 行为请求者”与“ 行为实现者”通常呈现一种“ 紧耦合”。但在 某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将 一组行为抽象为对象, 实现二者之间的松耦合。这就是 命令模式(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:
欢迎大家关注作者在文末评论、点赞、转发以及批评指正!
如果大家有更好的方法或有问题可以在文末评论一起讨论!
共同学习!
共同进步!
文末一句话:
苏轼说,平淡乃绚烂之极也。
品过人生的苦辣酸甜,淡,是人生最真的滋味。