设计模式2策略模式
做一个商场收银软件,营业员根据客户所购买商品的单价和数量,向客户收费
快速地写出代码
version_1.cpp #include using namespace std; class Cash { public: static double GetTotalPrice(double singlePrice, double total) { return singlePrice * total; } }; int main(int argc, char const *argv[]) { double price = 0, total = 0; cout << "请输入单价: " << endl; cin >> price; cout << "请输入数量: " << endl; cin >> total; cout << Cash::GetTotalPrice(price, total); return 0; }
现在加需求了,商场促销,全场打八折,满200减100;
这个没问题,根据简单工厂模式,可以根据不同的活动创建不同的收费类,计算出价格。
代码如下:
version_2.cpp #include using namespace std; class CashSuper { public: virtual double GetTotalPrice(double singlePrice, double total) { return singlePrice * total; } }; class CashNormal : public CashSuper { public: double GetTotalPrice(double singlePrice, double total) override { return singlePrice * total; } }; class CashDiscount : public CashSuper { private: double discount = 1; public: CashDiscount(double disc) : discount(disc) {}; double GetTotalPrice(double singlePrice, double total) override { return singlePrice * total * discount; } }; class CashReturn : public CashSuper { private: double moneyCondition = 0; double moneyReturn = 0; public: CashReturn() = delete; CashReturn(double condition, double ret) : moneyCondition(condition), moneyReturn(ret) {}; double GetTotalPrice(double singlePrice, double total) override { double totalPrice = singlePrice * total; if (totalPrice > moneyCondition) { totalPrice = totalPrice - floor(totalPrice / moneyCondition) * moneyReturn; } return totalPrice; } }; class CashFactory { public: static CashSuper* CreateCash(string& discountStr) { if (discountStr == "正常收费") { return new CashNormal; } else if (discountStr == "打八折") { return new CashDiscount(0.8); } else if (discountStr == "满200减100") { return new CashReturn(200, 100); } else { throw; } } }; int main(int argc, char const* argv[]) { double price = 0, total = 0; int type; cout << "请输入单价: " << endl; cin >> price; cout << "请输入数量: " << endl; cin >> total; cout << "请输入收费类型: " << endl << "1 正常收费, " << endl << "2 打八折, " << endl << "3 满200减100." << endl; cin >> type; string str; if (type == 1) { str.assign("正常收费"); } else if (type == 2) { str.assign("打八折"); } else if (type == 3) { str.assign("满200减100"); } else { cout << "收费类型不对" << endl; } CashSuper* cash = CashFactory::CreateCash(str); cout << cash->GetTotalPrice(price, total); return 0; }
简单工厂模式,可以解决问题,以后要加其他的活动,增加新的收费类就行了。
但是还可以优化,引出今天的策略模式。
策略模式
策略模式定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到算法的客户.
商场如何促销, 不管是打折还是返利, 都是算法的不同而已, 用工厂来生成算法, 没问题, 但是算法本身只是一种策略,
重要的是 这些算法可能随时会互相替换 .
代码改成策略模式 定义算法家族 也就是上个版本的 CashSuper 基类(策略类), 定义所支持的算法接口( GetTotalPrice ),
CashNormal , CashDiscount , CashReturn 具体的策略.定义一个context 类, 保存具体的策划类, 实现上下文接口
version_3.cpp #include using namespace std; class CashSuper { public: virtual double GetTotalPrice(double singlePrice, double total) { return singlePrice * total; } }; class CashNormal : public CashSuper { public: double GetTotalPrice(double singlePrice, double total) override { return singlePrice * total; } }; class CashDiscount : public CashSuper { private: double discount = 1; public: CashDiscount(double disc) : discount(disc) {}; double GetTotalPrice(double singlePrice, double total) override { return singlePrice * total * discount; } }; class CashReturn : public CashSuper { private: double moneyCondition = 0; double moneyReturn = 0; public: CashReturn() = delete; CashReturn(double condition, double ret) : moneyCondition(condition), moneyReturn(ret) {}; double GetTotalPrice(double singlePrice, double total) override { double totalPrice = singlePrice * total; if (totalPrice > moneyCondition) { totalPrice = totalPrice - floor(totalPrice / moneyCondition) * moneyReturn; } return totalPrice; } }; class CashContext { private: CashSuper* cash; public: CashContext(string& discountStr) { if (discountStr == "正常收费") { cash = new CashNormal; } else if (discountStr == "打八折") { cash = new CashDiscount(0.8); } else if (discountStr == "满200减100") { cash = new CashReturn(200, 100); } else { // 构造函数不建议抛异常 throw; } } double ContextInterface(double price, double total) { return cash->GetTotalPrice(price, total); } }; int main(int argc, char const* argv[]) { double price = 0, total = 0; int type; cout << "请输入单价: " << endl; cin >> price; cout << "请输入数量: " << endl; cin >> total; cout << "请输入收费类型: " << endl << "1 正常收费, " << endl << "2 打八折, " << endl << "3 满200减100." << endl; cin >> type; string str; if (type == 1) { str.assign("正常收费"); } else if (type == 2) { str.assign("打八折"); } else if (type == 3) { str.assign("满200减100"); } else { cout << "收费类型不对" << endl; } CashContext context(str); cout << context.ContextInterface(price, total); return 0; }
从这里我们可以看到, 策略模式这么写, 用的人只需要知道了解 CashContext 类就行了,
而简单工厂模式则需要认识 CashSuper , CashFactory 两个类.
策略模式的优点 策略模式定义一系列算法,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合 策略模式的算法基类为Context定义了一系列的可供重用的算法或行为。 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试