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