点外卖,让我想起了策略模式

Map+函数式接口代替策略模式 最近写了一个服务:根据优惠券的类型resourceType和编码resourceId来 查询 发放方式。 实现方式: 根据优惠券类型resourceType -> 确定查询哪个数据表 根据编码resourceId -> 查询派发方式grantType 优惠券有多种类型,分别对应了不同的数据库表: 美食满减红包,简称红包 商品购物券,简称购物券 QQ会员 外卖会员等 实际情况远不止这些,这个需求是要我们写一个业务分派的逻辑 第一个能想到的思路就是if-else或者switch case: 阅读详情

今天给大家分享的是策略模式,具体内容大纲如下:

生活案例

在这互联网时代,尤其是在城市中,有一帮骑着电瓶车,穿梭在大街小巷中,这帮人就是外卖小哥。

对于点外卖,我也点过不少。有一次,外卖下单的时候,我突然联想到了一个设计模式—策略模式。

策略模式是个啥?

策略模式:英文为Strategy Pattern,是指定义了算法家族、分别封装起来,让他们之间可以相互替换,此设计模式让算法的变化不会影响到使用算法的用户。

英文

Define a family of algorithms,encapsulate each one,and make them
interchangeable.

大致意思:定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。

在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

策略模式通用代码

java代码实现如下:

class Client {

    //抽象策略类 Strategy
    interface IStrategy {
        void algorithm();
    }

    //具体策略类 ConcreteStrategy
    static class ConcreteStrategyA implements IStrategy {

        @Override
        public void algorithm() {
            System.out.println("Strategy A");
        }
    }

    //具体策略类 ConcreteStrategy
    static class ConcreteStrategyB implements IStrategy {

        @Override
        public void algorithm() {
            System.out.println("Strategy B");
        }
    }

    //上下文环境
    static class Context {
        private IStrategy mStrategy;

        public Context(IStrategy strategy) {
            this.mStrategy = strategy;
        }

        public void algorithm() {
            this.mStrategy.algorithm();
        }
    }
    
   public static void main(String[] args) {
        //选择一个具体策略
        IStrategy strategy = new ConcreteStrategyA();
        //来一个上下文环境
        Context context = new Context(strategy);
        //客户端直接让上下文环境执行算法
        context.algorithm();
    }
}

从上面的通用代码,我们可以得知其UML图。

策略模式UML图

策略模式中的角色

从 UML 类图中,我们可以看到,策略模式主要包含三种角色:

上下文角色(Context):用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略,算法的直接访问,封装可能存在的变化;

抽象策略角色(Strategy):规定策略或算法的行为;

具体策略角色(ConcreteStrategy):具体的策略或算法实现;

策略模式优缺点

  • 优点

策略模式符合开闭原则

避免使用多重转换语句,比如:if…else、switch语句。

使用策略模式可以提高算法的保密性和安全性

  • 缺点

客户端必须知道所有策略,并且自行决定使用哪一种策略

代码中产生非常多的策略类,增加后期维护难度

策略模式使用场景

在日常开发中,策略模式适用于以下三种场景:

  • 针对同一类型问题,有多重处理方式,每一种都能独立解决问题。
  • 算法需要自由切换的场景。
  • 需要屏蔽算法规则的场景

这个说起来,还是不太好理解。
下面,我们就来使用生活案例来实现,让大家知道策略模式到底是怎么使用的。

支付案例代码重构,三个版本

外面下单,选择支付方式的时候,我觉这个功能,我们可以模仿着使用策略模式来实现一下。下面我们通过三个版本的迭代来实现,很有意思的。

第一版

先定义一个抽象类Pay:

//定义抽象类,我们可以把一些共用功能放在抽象类里实现
//比如:可用余额和本次支付金额进行比较,统一返回“支付失败”
public abstract class  Pay {
    abstract  void doPay();
}

下面模拟三种支付方式:

public class AliPay extends Pay {
    @Override
    public void doPay() {
        System.out.println("使用支付宝支付");
    }
}
public class UnionPay extends Pay {
    @Override
    public void doPay() {
        System.out.println("使用银联支付");
    }
}
public class WechatPay extends Pay {
    @Override
    public void doPay() {
        System.out.println("使用微信支付");
    }
}

我们再来进行支付:

public class PayTest {
    public static void main(String[] args) {
        //把选择权交给了用户
        Order order = new Order(new WechatPay());
        order.pay();*
    }
}

运行结果:

使用微信支付

这样我们就使用策略模式实现了简单版本的支付,但是其中有个很不爽的地方,就是每次还得自己手工new一个支付方式的对象。鉴于此,我们对第一版进行重构。

第二版
前面的实现都不变,变化的是发起支付的时候,只要前端传一个key过来就可以了,实现如下:

public class PayTest {
    public static void main(String[] args) { 

        String payKey = "Wechat";
        Order order = null;
        //通过判断前端传过来的key,判断使用哪种支付方式
        if (payKey.equals("Ali")) {
            order = new Order(new AliPay());
        } else if (payKey.equals("Wechat")) {
            order = new Order(new WechatPay());
        } else if (payKey.equals("union")) {
            order = new Order(new UnionPay());
        }else {
            //给出一个默认方式
            order = new Order(new WechatPay());
        }
        order.pay();
    }
}

运行结果

使用微信支付

这样我们就实现了,通过前端传过来的key,然后选出对应的支付方式。但是问题又来了,如果支付方式不断增多,那这里的if…else岂不是会越来越多吗?后续维护成本不是越来越大吗?
于是,第三版就有了。

第三版

在第二版中,会出现大量的if…else,会给后续的代码维护带来不便,于是在这一版中,我们对其进行重构,引入了注册式单例模式。

import java.util.HashMap;
import java.util.Map;

public enum PayStrategyEnum {
    ALI_PAY("Ali"),
    WECHAT_PAY("Wechat"),
    UNION_PAY("union"),
    //默认使用微信支付
    DEFAULT_PAY("Wechat");

    private String key;

    PayStrategyEnum(String key) {
        this.key = key;
    }

    private static final Map<String, Pay> payKeyMap = new HashMap();

    static {
        payKeyMap.put(ALI_PAY.key, new AliPay());
        payKeyMap.put(WECHAT_PAY.key, new WechatPay());
        payKeyMap.put(UNION_PAY.key, new UnionPay());
        payKeyMap.put(DEFAULT_PAY.key, new WechatPay());
    }

    public static Pay getPay(String payKey) {
        if (!payKeyMap.containsKey(payKey)) {
            return payKeyMap.get(DEFAULT_PAY.key);
        }
        return payKeyMap.get(payKey);
    }
}

然后,在订单支付的时候就变成了这样了:

public class PayTest {
    public static void main(String[] args) { 
        String payKey = "Wechat"; 
        Order order = new Order(PayStrategyEnum.getPay(payKey));
        order.pay();
    }
}

运行结果

使用微信支付

这样,我们就成功的规避了大量的if…else了,爽歪歪!

其实,上面三个版本的代码,是不是觉得很爽,这就是设计模式的强大之处。

PS:关于上面的三个版本,其实我们还可以继续完善,继续重构,感兴趣的你可以去试试如何继续重构。

总结

好了,今天的策略模式就到这里。其实,设计模式在大多数情况下,是不会单独存在的,都是使用多种设计模式混合起来使用的。

策略模式使用的就是面向对象的继承和多态机制,从而实现同一行为在不同场景下不同实现。
最好记的案例:

我们可以使用不同的交通工具去北京玩

坐飞机、坐高铁、坐汽车、开车、骑车。方式很多,你想选哪一条就选那一条。

最后用一句话来总结策略模式:

条条大路通罗马

使用策略模式代替嵌套的多层if-else – 后台在开发的过程中,需要进行各种逻辑判断,来判断某个按钮是否展示,某个操作是否允许。 所以嵌套了很多if-else判断,看起来很是头痛。修改了起来也要各方面考虑,防止逻辑错误,进行影响。 如图: 之前一直不知道会有怎样的处理方式更好。 先简介一下,这戏需要进行的逻辑判断: 判断当前用户是否有权限 判断用户状态, 判断时间等 其他 判断此条信息状态是否允许这个操作 此条信息其他信... 阅读详情

相关推荐

别再手动拆解字节了!用博图这个功能指令,5分钟搞定ARRAY转BOOL数组

本文详细介绍了西门子博图中`ARRAY_TO_BOOL`功能指令的高效应用,帮助工程师快速实现ARRAY到BOOL数组的转换。通过实战案例和参数配置指南,展示了如何5分钟内完成传统方法需半小时的任务,大幅提升PLC编程效率,特别适用于通信报文解析和设备状态监控。

weixin_42653691的博客 265

常用代码扩展点设计方式

在平时业务开中经常会遇到不同业务走不同的业务逻辑,为了代码的扩展性,不得不采取一些手段来对进行解耦,本文将介绍常用的代码扩展点实现方式,包括 Java SPI、dubbo SPI、策略模式及改进扩展点实现、Cola扩展点和抽象业务扩展点实现方式。...

聚焦AI技术前沿,深度解析大模型原理与多场景应用,探索最新突破与落地实践,助力行业洞悉趋势,驱动智能转型,赋能千行百业。 2606

VisualStudio2022配置CGAL

vs2022和vs2017安装配置boost没什么区别,只需要注意boost的msvc得是14.3的,这玩意跟visualstudio版本挂钩的。压缩包解压,得到下面这两文件,然后把auxiliary这个文件挪到CGAL-5.6里面就行了。我用cgal读取一个stl模型,并输出相关信息(想可视化的话需要安装Qt,不想装Qt也可以装VTK)然后下载下面这两个压缩包。照着下面的截图填就完事了。

weixin_43850909的博客 1171

cola架构:一种扩展点的实现思路浅析

在实际项目中,我们经常使用策略模式、或者状态模式来隔离同一接口下不同的实现逻辑,进而消除代码中ifelse硬编码分支,使代码结构更清晰,也大大提升了代码可读性;同时也满足了“开闭原则”,具备更高的可扩展性;在cola架构中,给出了一种“扩展点”的思路,本质还是策略模式的实现方式,通过“扩展点注解”的组装方式将策略模式实现类注册到容器中,供后续场景逻辑决策使用;

博客园 2690

Linux ELF文件解析:从file到readelf的完整工具链指南

ELF(可执行与可链接格式)是Linux系统中二进制文件的标准格式,定义了程序加载、内存布局和元数据组织方式。其核心原理在于通过程序头表描述执行视图、节区头表描述链接视图,实现代码与数据的结构化存储。这一格式的技术价值在于为程序调试、安全审计和性能优化提供了底层支持,尤其在动态链接、符号解析和内存保护机制中发挥关键作用。在应用场景上,系统管理员依赖ELF分析工具解决库依赖问题,安全研究员通过检查安全属性评估漏洞风险,开发者则利用反汇编进行代码调试。本文聚焦于file、readelf、objdump等工具链的

weixin_42691065的博客 635

AI视频生成本地搭建图文详细过程

在自己的电脑上搭建一个AI,主要用于通过自己输入的关键字来自动生成视频文案,把视频文案自动生成视频,再自动给视频配音配字幕。

张小三的博客 4695

DDD、六边形架构、整洁架构、菱形(cola)架构的深度解析

DDD(领域驱动设计)强调用“领域模型”承载业务知识,通过限界上下文划分边界;战术上用实体、值对象、聚合、领域服务、仓储、工厂、领域事件组织代码。**六边形架构(Ports & Adapters)把系统核心与外界交互隔离,所有 IO 通过端口(Port)与适配器(Adapter)**进出,核心可独立于框架、UI、DB 运行与测试。整洁架构(Clean Architecture)强调依赖方向只指向内圈(实体→用例→接口适配器→框架与驱动),与“洋葱/六边形”同宗同源,关注可演进、可测试。

dividividiv的博客 1304

BEVFusion实战:从零搭建LiDAR-Camera融合的3D目标检测环境(附避坑指南)

本文提供了BEVFusion实战指南,详细讲解如何从零搭建LiDAR-Camera融合的3D目标检测环境。内容涵盖环境配置、数据预处理、模型训练与性能优化等关键步骤,并附有实用的避坑技巧,帮助开发者高效部署这一先进的BEV感知算法。

p4q5r6s7t的博客 515

复杂度应对之道 - COLA应用架构

前言 从业这么多年,接触过银行的应用,Apple的应用,eBay的应用和现在阿里的应用,虽然分属于不同的公司,使用了不同的架构,但有一个共同点就是都很复杂。导致复杂性的原因有很多,如果从架构的层面看,主要有两点,一个是架构设计过于复杂,层次太多能把人绕晕。另一个是根本就没架构,ServiceImpl作为上帝类包揽一切,一杆捅到DAO(就简单场景而言,这种Transaction Script也还凑合...

我的新书《代码精进之路:从码农到工匠》 5万+

.net core 下的PostgreSQL 异常排查—— Exception while reading from stream (0x80004005)

最近以PostgreSQL为存储介质,实现了分布式缓存的一个组件开发,在经过开发环境的测试后,顺利推送到产品组的手里,经过开发环境的验证后,终于发布到测试环境了,但问题来了,产品组反应频繁出现访问异常,返回的信息大致是:Exception while reading from stream … (0x80004005) ????欢迎点赞 :???? 收藏 ⭐留言 ???? 如有错误敬请指正,赐人玫瑰,手留余香! ????本文作者:由webmote 原创,首发于 【优快云】 ????作者格言: 生活在

网尘的技术专栏 5844

把 Claude Code 接进 ABAP 世界,vibing-steampunk 到底能做什么

《Vibing Steampunk:AI Agent 与 ABAP 开发的工程化桥梁》摘要 Vibing Steampunk(vsp)是一个连接 AI Agent 与 SAP ABAP 开发环境的开源工具,通过 Model Context Protocol(MCP)将 ABAP 开发能力标准化。它解决了传统 ABAP 开发中 AI 辅助工具的局限性,使 Claude Code 等 AI 编程助手能够直接访问 ADT API,实现代码读写、调试、测试等完整开发流程。该工具采用 Go 语言开发,提供 147 个

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1935

点外卖,让我想起了 策略模式【原创】

关注“Java后端技术全栈”回复“000”获取大量电子书本篇文章是设计模式系列的第三篇:模板模式单例模式今天给大家分享的是策略模式,具体内容大纲如下:生活案例 在这互联网时代,尤其是在城市...

田维常 318

搞定最强大模型Gemini学生订阅,白嫖一年,包教包会

白嫖现在最强大模型

BUG猿的博客 2万+

深入解析工厂模式与策略模式的结合:从外卖平台折扣谈起

其实在很多的开发设计中,将工厂模式和策略模式的综合使用的案例是很多的,而且解决的实际问题也一样很多,本次对基本的简单工厂模式和策略模式做简单介绍,重点放在两者结合后的具体应用上做分析和讲解。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 7万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

策略模式:让“选择困难症”变得超简单!

不管哪种优惠,核心都是“根据订单金额算最终价格”。// 优惠策略接口(所有具体优惠的“模板”)// 计算最终价格的方法(参数是订单原价)我们需要一个“工具类”,帮我们选择当前适用的策略,并调用它的算法。这个类叫// 优惠策略上下文(负责选策略、算价格)// 当前使用的策略(默认是无门槛)// 动态切换策略(比如根据订单金额自动选最优)// 计算最终价格(调用当前策略的算法)策略模式的核心是“​​把变化的部分(算法)封装起来,不变的部分(调用逻辑)稳定下来​​”。

zhaomh2017的博客 662

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java 编程之策略模式详解

策略模式是一种行为型设计模式,它将一组可互换的算法封装成独立的类,使它们可以在运行时灵活切换。文章以外卖配送为例,展示了三种配送策略的实现:骑手专送、商家自送和用户自取。通过定义DeliveryStrategy接口和OrderContext上下文类,实现了配送策略的动态切换,体现了策略模式"解耦行为、易于扩展"的特点。该模式适用于支付方式、认证登录等多种场景,Java8还支持lambda简化实现。与状态模式不同,策略模式由外部主动设置策略而非内部自动切换。

superfreeman的专栏 1347

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

基于策略模式动态切换不同外卖平台API调用逻辑的架构设计

本文将介绍如何利用Java的策略模式(Strategy Pattern),配合工厂模式,实现对不同外卖平台API调用逻辑的优雅解耦与动态切换。策略模式将每个平台的逻辑封装成独立的类,通过统一的接口进行调用,新增平台只需新增类,无需修改原有代码。当商户发起请求时,系统根据商户ID查询其绑定的平台代码,然后动态获取策略,从而实现完全透明的多平台支持。在Controller或Service中,我们不再关心具体是哪个平台,只需要通过工厂获取策略并执行即可。针对不同的平台,我们编写具体的实现类。

120

设计模式之策略模式

策略模式

weixin_42445418的博客 355

外卖平台对接笔记(美团外卖,饿了么外卖)

乐观锁和悲观锁 乐观锁:认为在操作数据库时,没有另外一个人对数据库进行操作 悲观锁:认为自己在读数据库时,刚好有其他人也在写我们正在读的数据,悲观锁是对数据加锁,只有自己的数据读取完了,事务提交了,下一个人来能对数据进行操作 ...

若叶知秋的博客 7959

这可能是把策略模式讲的最通俗易懂得文章了

周末无事,窝在家里面看《权力的游戏第八季》,看的很是津津有味,虽然感觉有一点点要烂尾,但是我还是忍不住要去看到底谁可以坐上铁王座。 女朋友在一旁点外卖,好像是在使用优惠的时候遇到了一点点小问题。 策略 策略,指的是可以实现目标的方案集合,在某些特定情况下,策略之间是可...

weixin_30845171的博客 128

漫画:如何给女朋友解释什么是策略模式?

责编 | 伍杏玲 本文经授权转载自漫话编程(ID:mhcoding) 周末无事,窝在家里面看《权力的游戏第八季》,看的很是津津有味,虽然感觉有一点点要烂尾,但是我还是忍不住要去看到底谁可以坐上铁王座。 女朋友在一旁点外卖,好像是在使用优惠的时候遇到了一点点小问题。 策略 策略,指的是可以实现目标的方案集合,在某些特定情况下,策...

程序人生的博客 1128

设计模式在美团外卖营销业务中的实践

设计模式在美团外卖营销业务中的实践 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kw3bEFU6-1585027831030)(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==)...

m0_37941483的博客 2062

java23种设计模式—策略模式

策略模式是一种行为型设计模式,维基百科解释如下行为型设计模式:行为型设计模式是设计模式都一种,用来识别对象之间的常用交流模式并加以实现。如此可在进行这些交流活动时增强弹性。由此可以看出,行为型设计模式关注的是对象之间的通讯行为。定义策略模式:定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法都变化独立于使用算法都客户。角色分类 1.抽象策略接口 2.具体策略类 3.环境类UML图:常...

T-tian的博客 3125

这可能是把策略模式讲的最通俗易懂得文章了!

戳蓝字“优快云云计算”关注我们哦!技术头条:干货、简洁、多维全面。更多云计算精华知识尽在眼前,get要点、solve难题,统统不在话下!周末无事,窝在家里面看《权力的游...

优快云云计算 698

漫话:如何给女朋友解释什么是策略模式?

周末无事,窝在家里面看《权力的游戏第八季》,看的很是津津有味,虽然感觉有一点点要烂尾,但是我还是忍不住要去看到底谁可以坐上铁王座。女朋友在一旁点外卖,好像是在使用优惠的...

weixin_44742132的博客 214

java设计模式深度解析与实践:策略模式

通过本文,我们了解了策略模式的核心思想、实现方法以及适用场景。策略模式就像一个“瑞士军刀”,能够帮助我们轻松管理和切换不同的算法或行为。我是Java编程小能手,后续会带来更多有趣的设计模式和Java干货内容,欢迎随时交流~ 😄关注我,一起成为Java编程高手!

panqiangqiangqiang的博客 864
上一篇: 2021年金九银十:程序员从这两个开源项目开始准备
下一篇: 在小公司做开发太难了!面试面到我心态爆炸...
Python_cola
博客等级 码龄5年 2031粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值