源码可以在这里找到 大话设计模式C++版
大鸟给小菜布置了一个作业,做一个商场收银软件
营业员根据客户所购买商品的单价和数量,向客户收费。
UI设计
代码设计
//Widget.cpp
#pragma execution_character_set("utf-8")
#include "Widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->priceEdit->setValidator(new QDoubleValidator(0, 10000, 10, this)); //限制只能输入浮点数ui->numEdit->setValidator(new QIntValidator(0, 100, this)); //限制只能输入整数
}void Widget::on_okBtn_clicked()
{QString txtPrice = ui->priceEdit->text();QString txtNum = ui->numEdit->text();double totalPrice = Double() * Double();m_total += totalPrice;ui->listWidget->addItem(QString("单价:%1 数量:%2 合计:%3").arg(txtPrice).arg(txtNum).arg(totalPrice));ui->totalPriceLabel->setText(QString::number(m_total));
}void Widget::on_resetBtn_clicked()
{ui->priceEdit->clear();ui->numEdit->clear();ui->listWidget->clear();ui->totalPriceLabel->setText("0.00");m_total = 0;
}Widget::~Widget()
{delete ui;
}
增加打折优惠功能
UI设计
代码设计
//Widget.cpp
#pragma execution_character_set("utf-8")
#include "Widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->priceEdit->setValidator(new QDoubleValidator(0, 10000, 10, this));ui->numEdit->setValidator(new QIntValidator(0, 100, this));QStringList sl;sl << "正常收费" << "打八折" << "打七折" << "打五折";ui->calcCombox->addItems(sl);
}void Widget::on_okBtn_clicked()
{QString txtPrice = ui->priceEdit->text();QString txtNum = ui->numEdit->text();double totalPrice = 0;int calcType = ui->calcCombox->currentIndex();switch (calcType) {case 0:totalPrice = Double() * Double();break;case 1:totalPrice = Double() * Double() * 0.8;break;case 2:totalPrice = Double() * Double() * 0.7;break;case 3:totalPrice = Double() * Double() * 0.5;break;default:break;}m_total += totalPrice;QString calcText = ui->calcCombox->currentText();ui->listWidget->addItem(QString("单价:%1 数量:%2 %3 合计:%4").arg(txtPrice).arg(txtNum).arg(calcText).arg(totalPrice));ui->totalPriceLabel->setText(QString::number(m_total));
}void Widget::on_resetBtn_clicked()
{ui->priceEdit->clear();ui->numEdit->clear();ui->listWidget->clear();ui->totalPriceLabel->setText("0.00");m_total = 0;
}Widget::~Widget()
{delete ui;
}
问题1:switch case
里打折的部分除了折扣率不同,其他基本都是重复代码
问题2:如果要增加满减的计算方式,是否要在 on_okBtn_clicked函数
里增加更多的 case条件
优化方案:利用简单工厂模式把计算方法抽离出来,且打折的话需要接收折扣率,满减的话需要接收满多少,减多少
增加满300减100功能
代码设计
//CashSuper.h
class CashSuper
{
public:virtual double acceptCash(double money) = 0;virtual ~CashSuper() {};
};
//CashNormal.h
#include "CashSuper.h"class CashNormal : public CashSuper
{
public:virtual double acceptCash(double money) override {return money;}virtual ~CashNormal() {}
};
//CashRebate.h
#include "CashSuper.h"
#include <QString>class CashRebate : public CashSuper
{
private:double m_moneyRebate = 1.0;
public:CashRebate(QString moneyRebate) {m_moneyRebate = Double();}virtual double acceptCash(double money) override {return money * m_moneyRebate;}virtual ~CashRebate() {}
};
//CashReturn.h
#include "CashSuper.h"
#include <QString>class CashReturn : public CashSuper
{
private:double m_moneyCondition = 0.0;double m_moneyReturn = 0.0;
public:CashReturn(QString moneyCondition, QString moneyReturn) {m_moneyCondition = Double();m_moneyReturn = Double();}virtual double acceptCash(double money) override {double result = money;if (money >= m_moneyCondition) {result = money - int(money/m_moneyCondition) * m_moneyReturn;}return result;}virtual ~CashReturn() {}
};
//CashFactory.h
#include "CashSuper.h"
#include "CashNormal.h"
#include "CashRebate.h"
#include "CashReturn.h"class CashFactory
{
public:static CashSuper* createCashAccept(int type) {CashSuper* ret = nullptr;switch (type) {case 0:ret = new CashNormal();break;case 1:ret = new CashRebate("0.8");break;case 2:ret = new CashReturn("300", "100");break;default:break;}return ret;}
};
//Widget.cpp
#pragma execution_character_set("utf-8")
#include "Widget.h"
#include "ui_widget.h"
#include "CashFactory.h"
#include "CashSuper.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);initUIControl();
}void Widget::on_okBtn_clicked()
{QString txtPrice = ui->priceEdit->text();QString txtNum = ui->numEdit->text();double totalPrice = 0;CashSuper* cash = CashFactory::createCashAccept(ui->calcCombox->currentIndex());totalPrice = cash->Double()*Double());delete cash;m_total += totalPrice;QString calcText = ui->calcCombox->currentText();ui->listWidget->addItem(QString("单价:%1 数量:%2 %3 合计:%4").arg(txtPrice).arg(txtNum).arg(calcText).arg(totalPrice));ui->totalPriceLabel->setText(QString::number(m_total));
}void Widget::on_resetBtn_clicked()
{ui->priceEdit->clear();ui->numEdit->clear();ui->listWidget->clear();ui->totalPriceLabel->setText("0.00");m_total = 0;
}void Widget::initUIControl()
{initValidator();QStringList sl;sl << "正常收费" << "打8折" << "满300减100";ui->calcCombox->addItems(sl);
}void Widget::initValidator()
{ui->priceEdit->setValidator(new QDoubleValidator(0, 10000, 2, this));ui->numEdit->setValidator(new QIntValidator(0, 100, this));
}Widget::~Widget()
{delete ui;
}
大鸟看了后说:”简单工厂模式解决对象创建问题,工厂包括了所有的收费方式,商场是可能经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改动工厂,以致代码需要重新编译部署,很糟糕的处理方式。面对算法的时常变动,应该考虑使用策略模式。“
原本的CashSuper
,CashNormal
,CashRebate
,CashReturn
都不用更改。
引入 CashContext
类
//CashContext.h
#include "CashSuper.h"class CashContext
{
private:CashSuper* m_cs;
public: CashContext(CashSuper* cs) {m_cs = cs;}double GetResult(double money) {return m_cs->acceptCash(money);}
};
//Widget.cpp
#pragma execution_character_set("utf-8")
#include "Widget.h"
#include "ui_widget.h"
#include "CashSuper.h"
#include "CashContext.h"
#include "CashNormal.h"
#include "CashRebate.h"
#include "CashReturn.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);initUIControl();
}void Widget::on_okBtn_clicked()
{QString txtPrice = ui->priceEdit->text();QString txtNum = ui->numEdit->text();double totalPrice = 0;CashContext* cc = nullptr;CashSuper* cs = nullptr;switch (ui->calcCombox->currentIndex()) {case 0:cs = new CashNormal();cc = new CashContext(cs);break;case 1:cs = new CashRebate("0.8");cc = new CashContext(cs);break;case 2:cs = new CashReturn("300", "100");cc = new CashContext(cs);break;default:break;}totalPrice = cc->Double()*Double());delete cs;delete cc;m_total += totalPrice;QString calcText = ui->calcCombox->currentText();ui->listWidget->addItem(QString("单价:%1 数量:%2 %3 合计:%4").arg(txtPrice).arg(txtNum).arg(calcText).arg(totalPrice));ui->totalPriceLabel->setText(QString::number(m_total));
}void Widget::on_resetBtn_clicked()
{ui->priceEdit->clear();ui->numEdit->clear();ui->listWidget->clear();ui->totalPriceLabel->setText("0.00");m_total = 0;
}void Widget::initUIControl()
{initValidator();QStringList sl;sl << "正常收费" << "打8折" << "满300减100";ui->calcCombox->addItems(sl);
}void Widget::initValidator()
{ui->priceEdit->setValidator(new QDoubleValidator(0, 10000, 2, this));ui->numEdit->setValidator(new QIntValidator(0, 100, this));
}Widget::~Widget()
{delete ui;
}
问题:引入了策略模式,但是客户端又需要去判断使用哪一个算法了,看起来像走回老路了。考虑将简单工厂和策略模式结合。
//CashContext.h
#include "CashSuper.h"class CashContext
{
private:CashSuper* m_cs;
public: CashContext(int type); //不是具体收费策略对象,而是类型,简单工厂的输入double GetResult(double money);virtual ~CashContext();
};
//CashContext.cpp
#include "CashContext.h"
#include "CashNormal.h"
#include "CashRebate.h"
#include "CashReturn.h"CashContext::CashContext(int type)
{switch (type) {case 0:m_cs = new CashNormal();break;case 1:m_cs = new CashRebate("0.8");break;case 2:m_cs = new CashReturn("300", "100");break;default:break;}
}double CashContext::GetResult(double money)
{return m_cs->acceptCash(money);
}CashContext::~CashContext()
{delete m_cs;
}
//Widget.cpp
#pragma execution_character_set("utf-8")
#include "Widget.h"
#include "ui_widget.h"
#include "CashContext.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);initUIControl();
}void Widget::on_okBtn_clicked()
{QString txtPrice = ui->priceEdit->text();QString txtNum = ui->numEdit->text();double totalPrice = 0;//根据Combox的选择初始化CashContext中m_cs的类型CashContext* cc = new CashContext(ui->calcCombox->currentIndex());//其实就是调用cc中m_cs的acceptCash方法totalPrice = cc->Double()*Double());delete cc;m_total += totalPrice;QString calcText = ui->calcCombox->currentText();ui->listWidget->addItem(QString("单价:%1 数量:%2 %3 合计:%4").arg(txtPrice).arg(txtNum).arg(calcText).arg(totalPrice));ui->totalPriceLabel->setText(QString::number(m_total));
}void Widget::on_resetBtn_clicked()
{ui->priceEdit->clear();ui->numEdit->clear();ui->listWidget->clear();ui->totalPriceLabel->setText("0.00");m_total = 0;
}void Widget::initUIControl()
{initValidator();QStringList sl;sl << "正常收费" << "打8折" << "满300减100";ui->calcCombox->addItems(sl);
}void Widget::initValidator()
{ui->priceEdit->setValidator(new QDoubleValidator(0, 10000, 2, this));ui->numEdit->setValidator(new QIntValidator(0, 100, this));
}Widget::~Widget()
{delete ui;
}
策列模式+简单工厂:客户端只需要知道 CashContext类
只是用简单工厂:客户端需要知道 CashSuper类
和 CashFactory类
因此使用策略+简单工厂更加降低了客户端和底层业务代码的耦合度
本文发布于:2024-02-02 04:54:56,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170682089741489.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |