大家好,欢迎来到IT知识分享网。
策略(Strategy)模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。
策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
本章将以一下简单的商场收银系统来介绍策略模式,我们还是按照一步步改进程序的方法进行讲解。
先让我们来完成收银系统的1.0版
// main.cpp
#include <iostream>
using namespace std;
int main()
{
double total(0.0);
do
{
try
{
double price(0.0);
int count(0);
cout << "请输入商品单价:" << endl;
cin >> price;
cout << "请输入商品数量:" << endl;
cin >> count;
if (price > 0 && count > 0)
{
double totalSomeGoods = price * count;
total += totalSomeGoods;
cout << "单价:" << price << "元 数量:"
<< count << " 合计:" << totalSomeGoods << "元" << endl;
cout << "总计:" << total << "元" << endl;
}
}
catch (const exception &e)
{
cerr << e.what() << '\n';
}
} while (price > 0 && count > 0);
return 0;
}
程序运行效果示例
商场会经常做些打折的活动,那收银系统就需要增加打折的功能。商场收银系统V1.1
// main.cpp
#include <iostream>
using namespace std;
int main()
{
double total(0.0);
do
{
try
{
double price(0.0);
int count(0), mode(0);
cout << "请输入商品单价:" << endl;
cin >> price;
cout << "请输入商品数量:" << endl;
cin >> count;
cout << "请选择以下数字,确认商品的销售模式:" << endl;
cout << "1.原价 2.八折 3.七折" << endl;
cin >> mode;
if (price > 0 && count > 0)
{
double totalSomeGoods(0.0);
switch (mode)
{
case 1:
totalSomeGoods = price * count;
break;
case 2:
totalSomeGoods = price * count * 0.8;
case 3:
totalSomeGoods = price * count * 0.7;
break;
default:
cout << "选择的销售模式无效。" << endl;
continue;
}
total += totalSomeGoods;
cout << "单价:" << price << "元 数量:"
<< count << " 合计:" << totalSomeGoods << "元" << endl;
cout << "总计:" << total << "元" << endl;
}
}
catch (const exception &e)
{
cerr << e.what() << '\n';
}
} while (price > 0 && count > 0);
return 0;
}
程序运行效果示例
现在程序算是写出来了,但是重复代码很多,3个分支要执行的语句除了打折多少以外几乎没什么不同,而且程序扩展性不好。如果商场要做更多活动,例如满300返100,满200返50等,就要不停地加分支,这种情况下我们可以引入简单工厂模式。
// cash.h
#ifndef CASH_H
#define CASH_h
#include <cmath>
class Cash
{
public:
virtual double payCash(double price, int count) = 0;
};
class CashNormal : public Cash
{
public:
double payCash(double price, int count)
{
return price * count;
}
};
class CashDiscount : public Cash
{
public:
CashDiscount(double discount)
: discount(discount)
{}
double payCash(double price, int count)
{
return price * count * discount;
}
private:
double discount;
};
class CashRebate : public Cash
{
public:
CashRebate(double condition, double rebate)
: condition(condition)
, rebate(rebate)
{}
double payCash(double price, int count)
{
if (condition > 0)
{
int total = price * count;
if (total > 0)
{
total -= floor(total / condition) * rebate;
return total;
}
}
}
private:
double condition;
double rebate;
};
#endif
// cashfactory.h
#ifndef CASHFACTORY_H
#define CASHFACTORY_H
#include "cash.h"
#include <stdexcept>
class CashFactory
{
public:
static Cash *createCashMode(int mode)
{
Cash *cash = nullptr;
switch (mode)
{
case 1:
cash = new CashNormal();
break;
case 2:
cash = new CashDiscount(0.8);
break;
case 3:
cash = new CashDiscount(0.7);
break;
case 4:
cash = new CashRebate(300, 100); // 满300返100
break;
default:
throw std::invalid_argument("选择的模式无效");
break;
}
return cash;
}
};
#endif
// main.cpp
#include "cashfactory.h"
#include <iostream>
using namespace std;
int main()
{
double total(0.0);
string exit;
do
{
try
{
cout << "请输入商品单价:" << endl;
doube price(0);
cin >> price;
cout << "请输入商品数量:" << endl;
int count(0);
cin >> count;
if (price <= 0 || count <= 0)
{
cout << "商品单价或者商品数量不能小于或等于零" << endl;
continue;
}
cout << "请选择以下数字,确认商品的销售模式:" << endl;
cout << "1.原价 2.八折 3.七折 4.满300返100" << endl;
cin >> mode;
Cash *cash = CashFactory::createCashMode(mode);
double totalSomeGoods = cash->payCash(price, count);
delete cash;
cash = nullptr;
total += totalSomeGoods;
cout << "单价:" << price << "元 数量:"
<< count << " 合计:" << totalSomeGoods << "元" << endl;
cout << "总计:" << total << "元" << endl;
cout << "是否退出系统?(y/n)" << endl;
cin >> exit;
}
catch (const exception &e)
{
cerr << e.what() << '\n';
}
} while (exit.compare("y") != 0);
return 0;
}
简单工厂模式虽然也能解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包括所有的收费方式,商场是可能经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂,以致代码需重新编译部署,这真的是很糟糕的处理方式,所以用它不是最好的办法。面对算法的时常变动,我们可以引入策略模式。
商场收银系统V1.2。
创建策略类CashContext类
// cashcontext.h
#ifndef CASHCONTEXT_H
#define CASHCONTEXT_H
#include "cash.h"
#include <stdexcept>
class CashContext
{
public:
CashContext(int mode)
: mode(mode)
{}
double getResult(double price, int count)
{
Cash *cash(nullptr);
double result(0.0);
switch (mode)
{
case 1:
cash = new CashNormal();
result = cash->payCash(price, count);
break;
case 2:
cash = new CashDiscount(0.8);
result = cash->payCash(price, count);
break;
case 3:
cash = new CashDiscount(0.7);
result = cash->payCash(price, count);
break;
case 4:
cash = new CashRebate(300, 100);
result = cash->payCash(price, count);
break;
default:
throw std::invalid_argument("选择的模式无效");
break;
}
if (cash != nullptr)
{
delete cash;
cash = nullptr;
}
return result;
}
private:
int mode;
};
#endif
修改main.cpp
// main.cpp
#include "cashcontext.h"
#include <iostream>
using namespace std;
int main()
{
double total(0.0);
string exit;
do
{
try
{
cout << "请输入商品单价:" << endl;
double price(0);
cin >> price;
cout << "请输入商品数量:" << endl;
int count(0);
cin >> count;
if (price <= 0 || count <= 0)
{
cout << "商品单价或者商品数量不能小于或等于零" << endl;
continue;
}
cout << "请选择以下数字,确认商品的销售模式:" << endl;
cout << "1.原价 2.八折 3.七折 4.满300返100" << endl;
int mode(0);
cin >> mode;
CashContext *cashContext = new CashContext(mode);
double totalSomeGoods = cashContext->getResult(price, count);
delete cashContext;
cashContext = nullptr;
total += totalSomeGoods;
cout << "单价:" << price << "元 数量:"
<< count << " 合计:" << totalSomeGoods << "元" << endl;
cout << "总计:" << total << "元" << endl;
cout << "是否退出系统?(y/n)" << endl;
cin >> exit;
}
catch (const exception &e)
{
cerr << e.what() << '\n';
}
} while (exit.compare("y") != 0);
return 0;
}
最后,我们可以和之前使用简单工厂模式的main.cpp代码进行对比,使用简单工厂模式时我们要使用两个类:Cash和CashFactory,而使用策略模式只需要使用一个类CashContext类就可以了,这样耦合度进一步降低。
我们还可以使用简单工厂和策略模式相结合的方法进一步优化程序,这里只需要修改CashContext.h
#ifndef CASHCONTEXT_H
#define CASHCONTEXT_H
#include "cashfactory.h"
class CashContext
{
public:
CashContext(int mode)
: mode(mode)
{}
double getResult(double price, int count)
{
Cash *cash = CashFactory::createCashMode(mode);
double result = cash->payCash(price, count);
if (cash != nullptr)
{
delete cash;
cash = nullptr;
}
return result;
}
private:
int mode;
};
#endif
程序运行效果示例
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/55027.html