1. 程式人生 > >C++設計模式-使用Qt框架模擬策略模式(Strategy)+簡單工廠實現商場促銷

C++設計模式-使用Qt框架模擬策略模式(Strategy)+簡單工廠實現商場促銷

商城促銷:
1.簡單工廠模式:客戶端認識兩個類,CashSuper與CashFactory
2.簡單工廠模式 + 策略模式:客戶端只要認識CashContext就可以了,更加降低耦合性

策略模式解析:
策略模式是一種定義一系列演算法的方法,從概念上看,所有這些演算法完成的都是相同的工作,值是實現不同,它可以以相同的方式呼叫所以的演算法,減少了各種演算法類與使用演算法類之間的耦合[DPE]。
策略模式的Strategy層次為Context定義了一系列的可供重用的演算法或行為。繼承有助於析取出這些演算法的公共功能[DP]

程式執行截圖如下:

原始碼如下:

cash.h

#ifndef CASH_H
#define CASH_H

#include <QString>

class CashSuper{

public:
    virtual double acceptCash(double money) = 0;
    virtual ~CashSuper(){}
};

class CashNormal: public CashSuper{

public:
    double acceptCash(double money);
    ~CashNormal();
};

class CashRebate: public CashSuper{

public:
    CashRebate(const QString moneyRebate);
    double acceptCash(double money);
    ~CashRebate();

private:
    double m_moneyRebate;
};

class CashReturn: public CashSuper{

public:
    CashReturn(const QString moneyCondition, const QString moneyReturn);
    double acceptCash(double money);
    ~CashReturn();

private:
    double m_moneyCondition;
    double m_moneyReturn;
};

class CashContext{

public:
    CashContext(const QString type);
    ~CashContext();
    double getResult(double money);

private:
    CashSuper *m_cs;
};

#endif // CASH_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void insertListWidgetItem();
    void getCountPrice(double &countPrice);

protected slots:
    void submitBtnClicked();
    void clearBtnClicked();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

cash.cpp

#include "cash.h"
#include <QDebug>


double CashNormal::acceptCash(double money)
{
    return money;
}

CashNormal::~CashNormal()
{
    qDebug()<< "CashNormal::~CashSuper() called!";
}

CashRebate::CashRebate(const QString moneyRebate)
{
    m_moneyRebate = moneyRebate.toDouble();
}

double CashRebate::acceptCash(double money)
{
    return money * m_moneyRebate;
}

CashRebate::~CashRebate()
{
    qDebug()<< "CashRebate::~CashRebate() called!";
}

CashReturn::CashReturn(const QString moneyCondition, const QString moneyReturn)
{
    m_moneyCondition = moneyCondition.toDouble();
    m_moneyReturn = moneyReturn.toDouble();
}

double CashReturn::acceptCash(double money)
{
    double result = money;
    if(money >= m_moneyCondition)
        result = money - (int)(money / m_moneyCondition) * m_moneyReturn;

    return result;
}

CashReturn::~CashReturn()
{
    qDebug()<< "CashReturn::~CashReturn() called!";
}

CashContext::CashContext(const QString type)
{
    m_cs = NULL;


    if(type == "正常收費"){

        m_cs = new CashNormal;
    }
    else if(type == "滿300減100"){

        m_cs = new CashReturn("300", "100");
    }
    else if(type == "打8折"){

        m_cs = new CashRebate("0.8");
    }
    else if(type == "打5折"){

        m_cs = new CashRebate("0.5");
    }
    else{
        throw "the text of rebateComboBox is unnormal!";
    }
}

CashContext::~CashContext()
{
    delete m_cs;
}

double CashContext::getResult(double money)
{
    return m_cs->acceptCash(money);
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "cash.h"
#include <QMessageBox>
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("CSDN IT1995");

    ui->rebateComboBox->addItem("正常收費");
    ui->rebateComboBox->addItem("滿300減100");
    ui->rebateComboBox->addItem("打8折");
    ui->rebateComboBox->addItem("打5折");
    ui->rebateComboBox->addItem("丟擲異常");

    connect(ui->submitPushButton, SIGNAL(clicked(bool)), this, SLOT(submitBtnClicked()));
    connect(ui->clearPushButton, SIGNAL(clicked(bool)), this, SLOT(clearBtnClicked()));
}

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

void Widget::insertListWidgetItem()
{
    if(ui->goodsNumLineEdit->text().isEmpty() || ui->goodsPriceLineEdit->text().isEmpty())
        throw "goodsNumLineEdit or goodsPriceLineEdit is empty!";

    QString goodsNum = ui->goodsNumLineEdit->text();
    QString goodsPrice = ui->goodsPriceLineEdit->text();

    ui->goodsNumLineEdit->clear();
    ui->goodsPriceLineEdit->clear();
    ui->listWidget->addItem("商品單價:" + goodsPrice
                                + " 商品數量:" + goodsNum
                            + " 商品總價:" + QString::number(goodsPrice.toDouble() * goodsNum.toDouble()));
}

void Widget::getCountPrice(double &countPrice)
{
    for(int i = 0; i < ui->listWidget->count(); i++){
        QStringList list = ui->listWidget->item(i)->text().split("商品總價:");
        countPrice += list[list.size() - 1].toDouble();
    }
}

void Widget::submitBtnClicked()
{
    CashContext *cc = NULL;

    try{

        insertListWidgetItem();
        cc = new CashContext(ui->rebateComboBox->currentText());
        double countPrice = 0.0;
        getCountPrice(countPrice);
        QString priceStr = QString::number(cc->getResult(countPrice));
        ui->countPriceLabel->setText("總價:" + priceStr);

    }
    catch(const char *err){
        QMessageBox::information(this, "info", QString(err));
    }

    if(cc != NULL)
        delete cc;
}

void Widget::clearBtnClicked()
{
    ui->listWidget->clear();
    ui->countPriceLabel->setText("總價:");
}