第30章 混编模式(2)

30.2 迷你版交易系统(工厂模式+策略模式)

30.2.1 IC卡的两种金额

(1)固定金额:指员工不能提现的金额,这部分金额只能用来特定消费,即员工日常必需的消费,如食堂内吃饭、理发、健身等活动。

(2)自由金额:可以提现,也可以用于消费,

30.2.2 扣款策略(假设卡内有充足的余额)

(1)策略1:会对IC卡的两个金额产生影响

      IC卡固定余额 = IC卡现有固定金额 - 交易金额 / 2

      IC卡自由余额 = IC卡现有自由金额 - 交易金额 / 2

(2)策略2:全部从自由金额上操除

30.2.3 类图

 

【编程实验】迷你版交易系统

//设计模式混编——工厂模式+策略模式
//实例:迷你版的交易系统
/*
说明:
1. 每个员工都有一张IC卡,包含固定金额和自由金额
2. 固定金额指员工不能提现的金额,这部分金额只能用来特定消费,即
   员工日常必需的消费,如食堂内吃饭、理发、健身等活动
3. 自由金额:可以提现,也可以用于消费,
扣款策略(本例假设IC卡里有充足的余额)
策略1:会对IC卡的两个金额产生影响
      IC卡固定余额 = IC卡现有固定金额 - 交易金额 / 2
      IC卡自由余额 = IC卡现有自由金额 - 交易金额 / 2
策略2:全部从自由金额上操除。
*/
#include <iostream>
#include <string>
#include <list>

using namespace std;

//*******************************************辅助类***********************************
//交易信息
class Trade
{
private:
    string tradeNo; //交易编号
    int amount;     //交易金额
public:
    Trade():tradeNo(""),amount(0){}
    string getTradeNo(){return tradeNo;}
    void setTradeNo(string value)
    {
        tradeNo = value;
    }

    int getAmount(){return amount;}
    void setAmount(int value)
    {
        amount = value;
    }
};

//IC卡信息
class Card
{
private:
    string cardNo; //IC卡号码
    int steadyMoney; //固定交易金额
    int freeMoney;   //自由交易金额
public:
    string getCarNo(){return cardNo;}
    void setCardNo(string value)
    {
        cardNo = value;
    }

    int getSteadyMoney(){return steadyMoney;}
    void setSteadyMoney(int value)
    {
        steadyMoney = value;
    }

    int getFreeMoney(){return freeMoney;}
    void setFreeMoney(int value)
    {
        freeMoney = value;
    }
};

//**********************************策略接口*****************************
//扣款策略接口
class IDeduction
{
    //扣款,提供交易和卡信息,进行扣款,并返回扣款是否成功
public:
    virtual bool exec(Card& card, Trade& trade) = 0;
    virtual ~IDeduction(){}
};

//扣款策略1
class SteadyDeduction : public IDeduction
{
public:
    //固定交易扣款
    bool exec(Card& card, Trade& trade)
    {
        //分别从固定金额和自由金额中扣除
        int halfMoney = trade.getAmount() / 2;
        card.setFreeMoney(card.getFreeMoney() - halfMoney);
        card.setSteadyMoney(card.getSteadyMoney() - halfMoney);
        return true;
    }
};

//扣款策略2
class FreeDeduction :public IDeduction
{
public:
    //自由扣款
    bool exec(Card& card, Trade& trade)
    {
        //直接从自由余额中扣除
        card.setFreeMoney(card.getFreeMoney() - trade.getAmount());
        return true;
    }
};

//扣款策略的上下文环境
class DeductionContext
{
private:
    //持有扣款策略的引用
    IDeduction* deduction;
public:
    //构造函数传入策略
    DeductionContext(IDeduction* deduction)
    {
        this->deduction = deduction;
    }
    //执行扣款
    bool exec(Card& card, Trade& trade)
    {
        return deduction->exec(card, trade);
    }
};

//***********************************工厂类*****************************
class StrateFactory
{
public:
    static IDeduction* getDeduction(string type)
    {
        IDeduction* ret = NULL;
        if (type == "free")
        {
             ret = new FreeDeduction();
        }else if(type == "steady")
        {
             ret = new SteadyDeduction();
        }
        return ret;
    }
};

//初始化IC卡
void initIC(Card& card)
{
    //IC卡
    card.setCardNo("1100010001000");
    card.setFreeMoney(1000);//1000元
    card.setSteadyMoney(800); //800元
}

//打印出当前卡内交易金额
void showCard(Card& card)
{
    cout <<"IC卡编号:" << card.getCarNo() << endl;
    cout << "固定类型金额:" << card.getSteadyMoney() << endl;
    cout << "自由类型金额:" << card.getFreeMoney() << endl;
}

int main()
{

    Card card;
    initIC(card); //初始化一张IC卡

    cout <<"========初始化信息:========" << endl;
    showCard(card); //显示卡内信息

    //一条交易记录
    Trade trade;
    trade.setTradeNo("abcdef");
    trade.setAmount(100);

    //交易策略
    IDeduction* deduction = StrateFactory::getDeduction("steady"); //free或steady
    DeductionContext ctx(deduction);
    ctx.exec(card, trade);

    //交易成功,打印成功处理消息
    cout << "========交易凭证========" <<endl;
    cout << trade.getTradeNo() << "交易成功!"<<endl;
    cout << "本次发生的交易金额为:" << trade.getAmount() << "" << endl;

    //展示一下卡内信息
    showCard(card);

    delete deduction;

    return 0;
};
/*输出结果:
========初始化信息:========
IC卡编号:1100010001000
固定类型金额:800
自由类型金额:1000
========交易凭证========
abcdef交易成功!
本次发生的交易金额为:100元
IC卡编号:1100010001000
固定类型金额:750
自由类型金额:950
*/

30.2.4 小结

(1)策略模式:负责对扣款策略进行封装,保证两个策略可以自由切换,而且日后增加扣款策略也很容易。

(2)工厂方法模式:修正策略模式必须对外暴露具体策略问题,由工厂方法模式直接产生一个具体的策略对象,而其他模块则不需要依赖具体的策略

原文地址:https://www.cnblogs.com/5iedu/p/5683622.html