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