首页 > 其他分享 >策略模式:如何解决不同活动策略的营销推荐场景?

策略模式:如何解决不同活动策略的营销推荐场景?

时间:2024-09-01 23:25:10浏览次数:13  
标签:场景 策略 营销 模式 算法 使用 public 客户端

策略模式在实际的开发中很常用,最常见的应用场景是利用它来替换过多的 if-else 嵌套的逻辑判断。除此之外,它还能结合工厂模式给客户端提供非常灵活的使用体验。下面,我们一起来看看吧!

一、模式原理分析

策略模式的原始定义是:定义一系列算法,封装每个算法,并使它们可以互换。策略让算法独立于使用它的客户端而变化。

在这个定义中,策略模式明确表示应当由客户端自己决定在什么样的情况下使用哪些具体的策略。也就是说,服务端是作为一个策略的整体调控者,具体选择运行哪些策略其实是要交给客户端来决定的。比如,压缩文件的时候,你应该会提供一系列的不同压缩策略,比如,gzip、zip 等,至于客户端在什么时候使用 gzip,由客户端自行去决定。同时,gzip 还可以被替换为其他的压缩策略。

策略模式包含三个关键角色:

  • 上下文信息类(Context):用于存放和执行需要使用的具体策略类以及客户端调用的逻辑。

  • 抽象策略类(Strategy):定义策略的共有方法。

  • 具体策略类(StrategyA 等):实现抽象策略类定义的共有方法。

下面我们再来看看策略模式对应的代码实现:

public class Context {
    public void request(Strategy s) {
        s.operation();
    }
}
public interface Strategy {
    void operation();
}
public class StrategyA implements Strategy {
    @Override
    public void operation() {
        System.out.println("=== 执行策略 A ......");
    }
}
public class StrategyB implements Strategy {
    @Override
    public void operation() {
        System.out.println("=== 执行策略 B ......");
    }
}

从上面的代码实现我们能看出,策略模式的本质就是通过上下文信息类来作为中心控制单元,对不同的策略进行调度分配

二、使用场景分析

策略模式常见的使用场景有以下几种。

  • 系统中需要动态切换几种算法的场景。

  • 使用多重的条件选择语句来实现的业务场景。

  • 只希望客户端选择已经封装好的算法场景而不用关心算法实现细节。

  • 分离使用策略和创建策略的场景。

为了更好地理解策略模式的使用场景,下面我们还是通过一个简单的例子来演示说明。在日常的网上购物中,我们都希望购买到价格实惠的商品,而网站通常也会定期搞一些促销活动,比如,满 XXX 元减 XX 元、N 折扣、M 元秒杀等。这些活动通常是运营部门来制定的,运营希望能通过商品编号来推荐不同的促销活动。这时,作为系统的开发者,我们就需要开发针对一系列的营销策略进行推荐的系统功能。

那具体该怎么来实现呢?

首先,我们来定义策略 API——PromotionStrategy,每一种促销策略的算法都要实现该接口。该接口有一个 recommand 方法,接收并返回一个 int 对象,返回的就是推荐后可以参加的促销活动。实际上,推荐返回的可能是一个活动对象,这里用简单的数字代替。

public interface PromotionStrategy {
    /**
     * 返回1 代表 可以参加 满减活动
     * 返回2 代表 可以参加 N折优惠活动
     * 返回3 代表 可以参加 M元秒杀活动
     */
    int recommand(String skuId);
}

接下来,我们有三个类实现了 PromotionStrategy 接口,分别代表满减策略、N 折扣优惠活动策略和 M 元秒杀活动策略,类分别是 FullReduceStrategy、NPriceDiscountStrategy 和 MSpikeStrategy。

public class FullReduceStrategy implements PromotionStrategy {

    @Override
    public int recommand(String skuId) {
        System.out.println("=== 执行 满减活动");
        //推荐算法和逻辑写这里
        return 1;
    }
}
public class NPriceDiscountStrategy implements PromotionStrategy {
    @Override
    public int recommand(String skuId) {
        System.out.println("=== 执行 N 折扣优惠活动");
        //推荐算法和逻辑写这里
        return 2;
    }
}
public class MSpikeStrategy implements PromotionStrategy {
    @Override
    public int recommand(String skuId) {
        System.out.println("=== 执行 M 元秒杀活动");
        //推荐算法和逻辑写这里
        return 3;
    }
}

现在我们可以动手实现促销推荐的上下文信息类 Promotional,这里是存储和使用策略的地方。类中有一个 recommand 方法,用于执行推荐策略。它的构造函数有一个 PromotionStrategy 参数,可以在运行期间使用该参数决定使用哪种促销策略。

public class Promotional {
    private final PromotionStrategy strategy;
    public Promotional(PromotionStrategy strategy) {
        this.strategy = strategy;
    }
    public void recommand(String skuId) {
        strategy.recommand(skuId);
    }
}

最后,我们通过一个简单的单元测试代码来看下具体的运行结果。

public class Client {
    public static void main(String[] args) {
        Promotional fullReducePromotional = new Promotional(new FullReduceStrategy());
        fullReducePromotional.recommand("1122334455");
        Promotional nPriceDiscountPromotional = new Promotional(new NPriceDiscountStrategy());
        nPriceDiscountPromotional.recommand("6677889900");
        Promotional mSpikePromotional = new Promotional(new MSpikeStrategy());
        mSpikePromotional.recommand("11335577");
    }
}
//输出结果
=== 执行 满减活动
=== 执行 n折扣优惠活动
=== 执行 m元秒杀活动

三、为什么使用策略模式?

分析完策略模式的原理和使用场景后,我们再来说说使用策略模式的原因,主要有以下三个。

第一个,为了提升代码的可维护性。 在实际开发中,有许多算法可以实现某一功能,如查找、排序等,通过 if-else 等条件判断语句来进行选择非常方便。但是这就会带来一个问题:当在这个算法类中封装了大量查找算法时,该类的代码就会变得非常复杂,维护也会突然就变得非常困难。虽然策略模式看上去比较笨重,但实际上在每一次新增策略时都通过新增类来进行隔离,短期虽然不如直接写 if-else 来得效率高,但长期来看,维护单一的简单类耗费的时间其实远远低于维护一个超大的复杂类。

第二个,为了动态快速地替换更多的算法。 从上面的分析你会发现,策略模式最大的作用在于分离使用算法的逻辑和算法自身实现的逻辑,这样就意味着当我们想要优化算法自身的实现逻辑时就变得非常便捷,一方面可以采用最新的算法实现逻辑,另一方面可以直接弃用旧算法而采用新算法。使用策略模式能够很方便地进行替换。

第三个,为了应对需要频繁更换策略的场景。 比如,用户推荐类场景。特别是对于一些 C 端产品来说,在获取了用户的反馈数据后,会根据用户的特性制定不同的运营策略,这时如果采用 if-else 的方式编码,那么每一次的策略变化都会导致系统代码的修改,从运营的角度看是不可接受的,而采用策略模式就能很容易地解决这个问题。

四、策略模式的优缺点是什么?

通过上面的分析,我们可以得出使用策略模式主要有以下几个优点。

  • 提供良好的代码扩展性。 每一个策略都是对应生成一个新的具体策略类,满足开闭原则,同时满足里氏替换原则,可以任意替换相同的策略,这样用户可以在不修改原有系统的基础上选择算法或行为,同时也可以灵活地增加新的算法或行为。

  • 提供了一种管理多个不同算法策略的办法。 策略模式提供了一种很好的思路,可以将算法的实现和使用算法的代码隔离开来,这样就能很好地管理不同的算法。

  • 提供使用组合替换继承的办法。 策略模式使用组合的方式来替代继承,避免了子类出现异常而影响父类。

  • 能够降低使用多重条件(if-else)嵌套语句的理解难度。 在实际的开发中,使用 if-else 是非常常见的编程方法,但是随着业务逻辑变得越来越复杂,如果一味地增加 if-else,会让代码变得非常难以理解和维护,使用策略模式则能避免这些问题的出现。

  • 在运行时动态切换算法,提升代码灵活性。 由于策略模式将算法的选择权交给了客户端,那么客户端可以根据自身的需求灵活地切换算法。

同样,策略模式也不是万能的,它也有一些缺点。

  • 客户端的学习成本变高。 虽然策略模式让客户端自行决定使用哪一个策略,看上去很自由,但实际上隐含着客户必须要知道所有的策略才能做选择的事实。一旦新增或修改策略,客户端都需要知道。

  • 具体策略类的数量会剧增,增加维护成本。 由于每一个策略都对应一个具体策略类,所以当策略比较庞大时,需要维护的类数量也会激增。

  • 不如函数式编程简洁。 现在有很多编程语言都支持函数式——允许在一组匿名函数中实现不同版本的算法。对于一些小型的策略来说,使用函数式编程就能解决问题,但使用策略模式反而过于复杂。

策略模式最大的用处是能在运行时改变代码的算法行为,同时给使用者提供一种可以根据情况来选择算法的途径。

虽然策略模式是一个比较容易理解和使用的设计模式,但是却增加了使用者的难度,因为可能需要在了解了所有的策略后才能做出决策。即便是类似排序这样简单的算法,不同使用者的选择也可能完全不同,如果交给使用者来选择,就意味着使用者需要了解不同排序算法的优劣,才能更好地做出选择。

不过,策略模式对算法起到了很好的封装作用,通过使用算法和创建算法的分离,将算法实现的复杂性放到了子类去解决。同时,策略模式还可以随时进行替换,对于一些老旧的算法,可以很方便地进行替换和升级。

文章(专栏)将持续更新,欢迎关注公众号:服务端技术精选。欢迎点赞、关注、转发

个人小工具程序上线啦,通过公众号(服务端技术精选)菜单【个人工具】即可体验,欢迎大家体验后提出优化意见

标签:场景,策略,营销,模式,算法,使用,public,客户端
From: https://blog.51cto.com/jiangyi/11890528

相关文章

  • Ceph Reef(18.2.X)之对象访问策略配置
    作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。目录一.对象存储概述1.对象存储的访问方式2.基于http方式访问对象存储注意事项3.查看存储桶默认策略二.定制策略1.定制......
  • Java代码优化:提升应用性能的策略
    Java代码优化:提升应用性能的策略大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java开发中,代码优化是提升应用性能的关键步骤。通过优化代码,可以减少内存使用、提高执行速度和增强程序的响应能力。本文将探讨一些有效的Java代码优化策略。算法优......
  • ‌工厂模式(Factory Pattern)和策略模式(Strategy Pattern)的主要区别!整理不易请及时收
    成长路上不孤单......
  • kube-scheduler调度策略之预选策略(三)
    一、概述摘要:本文我们继续分析源码,并聚焦在预选策略的调度过程的执行。二、正文说明:基于kubernetesv1.12.0源码分析上文我们说的(g*genericScheduler)Schedule()函数调用了findNodesThatFit()执行预选策略。2.1findNodesThatFit先找到改函数对应的源码//k8......
  • 【运维系列】如何为日志开放安全策略
    网络中日志流量的典型组网如【图1】所示。通常,路由器、交换机、服务器等设备向日志主机发送Syslog日志信息使用UDP514端口。如果日志流经防火墙,需要在防火墙上开放安全策略。【图1】日志输出典型组网防火墙支持输出多种类型的日志。在输出日志信息到日志服务器时,部分日志......
  • 【运维系列】如何为HTTP、HTTPS和RESTCONF开放安全策略
    防火墙提供了简单易用的WebUI。用户从浏览器访问承载在防火墙上的HTTPServer,可以完成绝大部分的配置管理工作。缺省情况下,防火墙启用HTTPS服务,服务端口为8443,且不可修改。从浏览器发起的HTTP访问会被重定向到HTTPS。RESTCONF以HTTP协议的方法提供了NETCONF协议的核心功能,编程接......
  • 【运维系列】如何为Telnet开放安全策略
    常见的管理协议,如Telnet、SSH、FTP,具有相似的业务模型。先看Telnet。如图1-1所示,网络中可能有三种业务访问关系。【入方向(Inbound)流量】:从管理终端Telnet防火墙的接口地址,是访问防火墙的流量。【出方向(Outbound)流量】:从防火墙Telnet服务器的地址,属于从防火墙发出的流量。【穿墙......
  • 【运维系列】如何为Ping和Tracert开放安全策略
    Ping和Tracert是基于ICMP协议的常用网络诊断工具。ICMP即互联网控制消息协议(InternetControlMessageProtocol),用于在IP网络中传递控制消息,如报告错误、交换状态信息等。这些消息为管理员诊断网络故障提供帮助。一、Ping为了正常的网络诊断需要,你可能需要允许防火墙主动Ping上......
  • 【运维系列】如何为NETCONF开放安全策略
    NETCONF(NetworkConfigurationProtocol,网络配置协议)是一种基于XML的网络管理协议,它提供了一种对网络设备进行配置和管理的可编程方法。NETCONF协议的传输层可以是BEEP、SSH、TLS或SOAP。由于RFC协议规定必须支持SSH,所以目前SSH是NETCONF使用最广泛的传输层协议,当前华为防火墙产......
  • 【运维系列】如何为SNMP开放安全策略
    SNMP是最广泛使用的网络管理协议。网管软件作为SNMPManager,向被管设备中的SNMPAgent发出管理操作的请求。被管设备在检测到异常时,也会主动向SNMPManager发送Trap信息。也就是说,网管软件和被管设备都会主动发起连接,如图6-1所示。【图】SNMP典型组网和业务访问关系因此,你......