策略模式定义多种处理同一种场景的不同算法,这些算法可在不影响用户的情况下互相替换。
应用场景
某会员制商场有两种级别会员:银卡会员、黄金会员,分别享有9折、8折购物优惠。同时不同的会员用户在生日当天购物,会赠送不同的生日礼物。
分析
场景比较简单,需要解决的问题是区分不同类型的顾客享有不同的权益(折扣和生日礼物)。
按照平常的编码习惯,通常会在需要区分用户等级的业务上加上if判断,实现不同等级顾客应享有的不同权益。这种方案能快速的解决实际问题,但是随着业务需要,商场又要引进更高逼格的会员类型,譬如白金会员、钻石会员等。此时,需要在散落在各处的业务代码上加上if补丁。这种做法会引来如下问题:
解决方案
引入策略模式,将用户等级抽象,分别定义出用户所有的行为,不同等级的用户各自实现该等级应享有的权益。
CShop:商场类。实现不同等级顾客的折扣结算、生日礼物等。持有CConsumer指针,根据需要指向具体的顾客实例(CCommonUser、CSilverUser、CGoldUser)。
CConsume:顾客抽象类。定义顾客所有的行为接口。
CCommonUser、CSilverUser、CGoldUser:具体顾客类。不同等级顾客实现有差异部分的接口。
执行效果
$ ./exe
---------------------------------
All Cost : 1000.00.
User Type : Common User.
Discount : 1.00.
Actual Payment: 1000.00.
---------------------------------
All Cost : 1000.00.
User Type : Silver User.
Discount : 0.90.
Actual Payment: 900.00.
---------------------------------
All Cost : 1000.00.
User Type : Gold User.
Discount : 0.80.
Actual Payment: 800.00.
客户端实现
int main(int argc, char *argv[])
{
CShop theShop;
float cost = 1000.0;
// 普通用户
MAIN_LOG("\n---------------------------------\n");
MAIN_LOG(" All Cost : %0.2f. \n"
" User Type : %s. \n"
" Discount : %0.2f. \n"
" Actual Payment: %0.2f. \n",
cost,
theShop.GetUserDesc().c_str(),
theShop.GetCurrentDiscountRate(),
theShop.GetRealPrice(cost));
// 切换白银会员
MAIN_LOG("\n---------------------------------\n");
theShop.SetConsumer(COSUMER_SILVER);
MAIN_LOG(" All Cost : %0.2f. \n"
" User Type : %s. \n"
" Discount : %0.2f. \n"
" Actual Payment: %0.2f. \n",
cost,
theShop.GetUserDesc().c_str(),
theShop.GetCurrentDiscountRate(),
theShop.GetRealPrice(cost));
// 切换黄金会员
MAIN_LOG("\n---------------------------------\n");
theShop.SetConsumer(COSUMER_GOLD);
MAIN_LOG(" All Cost : %0.2f. \n"
" User Type : %s. \n"
" Discount : %0.2f. \n"
" Actual Payment: %0.2f. \n",
cost,
theShop.GetUserDesc().c_str(),
theShop.GetCurrentDiscountRate(),
theShop.GetRealPrice(cost));
return 0;
}
商店类接口
class CShop
{
public:
CShop();
~CShop();
std::string GetUserDesc() { return mConsumer->mUserDesc; }
float GetRealPrice(float price);
int BirthdayPresent();
int SetConsumer(EConsumerType type);
void SetCurrentDiscountRate(float rate);
float GetCurrentDiscountRate();
private:
CConsumer* mConsumer;
};
更新顾客类型
int CShop::SetConsumer(EConsumerType type)
{
switch (type)
{
case COSUMER_COMMON:
mConsumer = CCommonUser::GetInstance();
break;
case COSUMER_SILVER:
mConsumer = CSilverUser::GetInstance();
break;
case COSUMER_GOLD:
mConsumer = CGoldUser::GetInstance();
break;
default:
break;
}
if (NULL == mConsumer) {
return -1;
}
return 0;
}
顾客类抽象接口
class CConsumer
{
public:
float mDiscountRate;
std::string mUserDesc;
CConsumer() : mDiscountRate(1.0)
{
}
virtual ~CConsumer()
{
}
void SetDiscountRate(float rate)
{
mDiscountRate = rate;
}
float GetDiscountRate()
{
return mDiscountRate;
}
float GetRealPrice(float price)
{
return mDiscountRate * price;
}
virtual int GetBirthdayPresent() = 0;
};
具体顾客类:黄金会员
class CGoldUser : public CConsumer
{
public:
CGoldUser();
~CGoldUser();
static CGoldUser* GetInstance();
int GetBirthdayPresent();
};
客户端接口
int main(int argc, char *argv[])
{
CShop theShop;
float cost = 1000.0;
// 普通用户
MAIN_LOG("\n---------------------------------\n");
MAIN_LOG(" All Cost : %0.2f. \n"
" User Type : %s. \n"
" Discount : %0.2f. \n"
" Actual Payment: %0.2f. \n",
cost,
theShop.GetUserDesc().c_str(),
theShop.GetCurrentDiscountRate(),
theShop.GetRealPrice(cost));
// 切换白银会员
MAIN_LOG("\n---------------------------------\n");
theShop.SetConsumer(COSUMER_SILVER);
MAIN_LOG(" All Cost : %0.2f. \n"
" User Type : %s. \n"
" Discount : %0.2f. \n"
" Actual Payment: %0.2f. \n",
cost,
theShop.GetUserDesc().c_str(),
theShop.GetCurrentDiscountRate(),
theShop.GetRealPrice(cost));
// 切换黄金会员
MAIN_LOG("\n---------------------------------\n");
theShop.SetConsumer(COSUMER_GOLD);
MAIN_LOG(" All Cost : %0.2f. \n"
" User Type : %s. \n"
" Discount : %0.2f. \n"
" Actual Payment: %0.2f. \n",
cost,
theShop.GetUserDesc().c_str(),
theShop.GetCurrentDiscountRate(),
theShop.GetRealPrice(cost));
return 0;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。