Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++设计模式 - 策略模式

C++设计模式 - 策略模式

原创
作者头像
开源519
修改于 2022-01-18 08:00:19
修改于 2022-01-18 08:00:19
3680
举报
文章被收录于专栏:开源519开源519

策略模式

策略模式定义多种处理同一种场景的不同算法,这些算法可在不影响用户的情况下互相替换。

场景

应用场景

某会员制商场有两种级别会员:银卡会员、黄金会员,分别享有9折、8折购物优惠。同时不同的会员用户在生日当天购物,会赠送不同的生日礼物。

分析

场景比较简单,需要解决的问题是区分不同类型的顾客享有不同的权益(折扣和生日礼物)。

按照平常的编码习惯,通常会在需要区分用户等级的业务上加上if判断,实现不同等级顾客应享有的不同权益。这种方案能快速的解决实际问题,但是随着业务需要,商场又要引进更高逼格的会员类型,譬如白金会员、钻石会员等。此时,需要在散落在各处的业务代码上加上if补丁。这种做法会引来如下问题:

  • 业务代码散落各处,容易出现漏加if的情况,又难以验证。
  • 时间推移,if会越来越多,导致分支变多,代码走向模糊,影响代码维护。

解决方案

引入策略模式,将用户等级抽象,分别定义出用户所有的行为,不同等级的用户各自实现该等级应享有的权益。

类图

策略模式
策略模式

CShop:商场类。实现不同等级顾客的折扣结算、生日礼物等。持有CConsumer指针,根据需要指向具体的顾客实例(CCommonUser、CSilverUser、CGoldUser)。

CConsume:顾客抽象类。定义顾客所有的行为接口。

CCommonUser、CSilverUser、CGoldUser:具体顾客类。不同等级顾客实现有差异部分的接口。

效果

执行效果

代码语言:c++
AI代码解释
复制
$ ./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.   

客户端实现

代码语言:c++
AI代码解释
复制
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;
}

总结

  • 策略模式的实现原理比较简单,主要是改变持有指针的指向,即可实现不同方案的切换。更改为外部条件输入匹配对应的实例,便可以做到客户端代码无需改变自动切换不同方案的效果。
  • 满足开闭原则。当需增加策略时,只需要派生一个新的策略即可,而无需修改现有代码。相对以前的做法,更加安全快捷。
  • 在代码运行时,也可以动态切换策略。
  • 策略模式命令模式有点相像。两者的实现方式类似,应对的场景不同。策略模式针对的是同一个行为不同的算法实现;命令模式针对是一个命令对应一个解决的方法。
  • 全部源码可在公众号后台输入标题获取。

源码

商店类接口

代码语言:c++
AI代码解释
复制
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;
};

更新顾客类型

代码语言:c++
AI代码解释
复制
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;
}

顾客类抽象接口

代码语言:c++
AI代码解释
复制
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;
};

具体顾客类:黄金会员

代码语言:c++
AI代码解释
复制
class CGoldUser : public CConsumer
{
public:
    CGoldUser();

    ~CGoldUser();

    static CGoldUser* GetInstance();

    int GetBirthdayPresent();
};

客户端接口

代码语言:c++
AI代码解释
复制
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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
🔥【设计模式】策略模式
大家好,我是“前端小鑫同学”,😇长期从事前端开发,安卓开发,热衷技术,在编程路上越走越远~ 场景介绍: 我们有一款识视频App,目前可以登录的用户分为临时用户、普通用户、管理员三种,还有会员等级的一个分类,主要有无会员、普通会员,高级会员。在最初设计稿中指明,可以观赏高清视频的只能是普通用户并且开通了高级会员,可以登录管理平台的支能是管理员。 需求描述: 根据上面的描述我们先准备一个权限和一个会员的枚举: // 1. 临时用户/普通用户/管理员 enum Role { casual, genera
前端小鑫同学
2022/12/26
2510
C++设计模式——策略模式
在软件开发中,设计模式是提高代码可读性、可维护性和可扩展性的重要工具之一。其中,策略模式是一种行为型设计模式,它允许在运行时选择不同算法的行为,并支持不同策略的无缝切换。
程序员的园
2024/07/18
1530
C++设计模式——策略模式
设计模式之策略模式
策略模式(Strategy Pattern)隶属于设计模式中的行为型模式,是日常开发中使用最广的一个模式,相对于其他模式,自认为这个模式是最容易理解和使用的。
Dylan Liu
2019/08/22
6380
策略模式虽好,Policy-based design更佳
策略模式(设计模式——策略模式)大家耳熟能详,简言之,策略模式基于运虚表指针实现多态,但运行时的多态是有时间成本的。对于性能要求高的场景,策略模式反而不是最优选择。
程序员的园
2024/07/18
1370
策略模式虽好,Policy-based design更佳
大厂面试必备之设计模式:漫画策略模式
官方定义不太好理解,我翻译一下,在策略模式中,会针对一个行为(比如支付),定义多个实现类,每个类都封装具体的实现算法,并且为了保证他们是同一行为,通常这些实现类,都会实现同一个接口。比如微信支付,支付宝支付,微信好友支付,QQ支付,缺省支付方式都是一个算法。
天才少年
2020/07/04
4660
大厂面试必备之设计模式:漫画策略模式
php设计模式(二十三):策略模式(Strategy)
策略模式又称为:Strategy。策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类,以使算法的对象能够相互替换。
陈大剩博客
2023/07/09
3060
php设计模式(二十三):策略模式(Strategy)
白话设计模式之策略模式
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户,比如公司都会为我们每个人交公积金,但是每个公司所交的比例又不一样,又如我们每个每个人出行所选择的交通工具也不一样,有人开劳斯莱斯出行,有人开宾利,而我要么坐地铁,要么骑共享单车
小四的技术之旅
2022/07/26
3700
白话设计模式之策略模式
通俗易懂设计模式解析——策略模式
  今天我们来看策略模式【Stragety Pattern【行为型】】,这个模式还是比较好理解的。策略怎么理解呢?一般是指:1. 可以实现目标的方案集合;2. 根据形势发展而制定的行动方针和斗争方法;3. 有斗争艺术,能注意方式方法。总的来说呢就是针对一个目的的不同的方法集合。这里要讲的策略模式怎么理解呢?简单的说就是对于一个类的行为或者其算法可以在运行时更改替换。
小世界的野孩子
2019/10/16
5340
通俗易懂设计模式解析——策略模式
解锁新姿势:探讨复杂的 if-else 语句“优雅处理”的思路
在之前文章说到,简单 if-else,可以使用 卫语句 进行优化。但是在实际开发中,往往不是简单 if-else 结构,我们通常会不经意间写下如下代码:
用户1516716
2020/02/20
8250
Java常用设计模式--策略模式(Strategy Pattern)
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
gang_luo
2020/08/13
3100
设计模式-策略模式
每当想起去书店买书,老是觉得老火,为啥同样一本书,卖我总是比别人贵呢?我买就只打8折为啥其他有7折的???人品问题???不是的,是因为会员制度,不同的会员等级享受不同的折扣,这个很类似我们的策略模式,不同的角色可以定义不同的算法。
逍遥壮士
2020/09/18
4460
设计模式-策略模式
Java设计模式——策略模式[通俗易懂]
策略模式:策略模式是一种行为型模式,它将对象和行为分开,将行为定义为 一个行为接口 和 具体行为的实现。策略模式最大的特点是行为的变化,行为之间可以相互替换。每个if判断都可以理解为就是一个策略。本模式使得算法可独立于使用它的用户而变化
全栈程序员站长
2022/09/30
4700
Java设计模式——策略模式[通俗易懂]
一起学设计模式 - 策略模式
策略模式: 是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。下面就以一个示意性的实现讲解策略模式实例的结构。
battcn
2018/08/03
3920
一起学设计模式 - 策略模式
设计模式之 - 策略落实
策略模式:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式的变化,不会影响到使用算法的客户。
一个程序员的成长
2020/11/25
3630
设计模式之 - 策略落实
设计模式 | 策略模式及典型应用
在软件开发中,我们也常常会遇到类似的情况,实现某一个功能有多条途径,每一条途径对应一种算法,此时我们可以使用一种设计模式来实现灵活地选择解决途径,也能够方便地增加新的解决途径。
小旋锋
2019/01/21
1.3K0
设计模式丨策略模式
如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
星河造梦坊官方
2024/08/15
1480
设计模式丨策略模式
前端也要学系列:设计模式之策略模式
上边这句话,从字面来看很简单。但是如何在开发过程中去应用,仅凭一个定义依然是一头雾水。以笔者曾经做过的商户进销存系统为例:
司想君
2018/08/01
3550
前端也要学系列:设计模式之策略模式
设计模式学习之策略模式
**定义:**策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化。
老马的编程之旅
2022/06/22
2010
设计模式学习之策略模式
前端的设计模式系列-策略模式
代码也写了几年了,设计模式处于看了忘,忘了看的状态,最近对设计模式有了点感觉,索性就再学习总结下吧。
windliang
2022/08/20
2850
前端的设计模式系列-策略模式
设计模式的征途—18.策略(Strategy)模式
俗话说条条大路通罗马,很多情况下实现某个目标地途径都不只一条。在软件开发中,也会时常遇到这样的情况,实现某一个功能有多条途径,每一条途径都对应一种算法。此时,可以使用一种设计模式来实现灵活地选择解决途径,也能够方便地增加新的解决途径。
Edison Zhou
2018/08/21
3900
设计模式的征途—18.策略(Strategy)模式
相关推荐
🔥【设计模式】策略模式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档