策略模式:优雅应对多变的业务需求
一、策略模式基础概念
策略模式(Strategy Pattern) 是一种行为型设计模式,它通过定义一系列可互换的算法族,并将每个算法封装成独立的策略类,使得算法可以独立于使用它的客户端变化。策略模式的核心思想是 “将算法的定义与使用分离”,从而解决在复杂业务场景中因条件分支过多导致的代码臃肿、维护困难等问题。
核心角色
- 环境类(Context):持有策略对象的引用,负责调用具体策略。
- 抽象策略(Strategy):定义算法接口,声明策略方法的规范。
- 具体策略(Concrete Strategy):实现抽象策略接口,提供具体的算法实现。
二、简单案例:支付方式选择
假设需要实现一个支持多种支付方式的系统(支付宝、微信、银行卡),通过策略模式可以灵活扩展支付方式,避免冗长的 if-else 判断。
1. 定义抽象策略接口
public interface PaymentStrategy {void pay(double amount);
}
2. 实现具体策略类
// 支付宝支付
public class AlipayStrategy implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("支付宝支付:" + amount + "元");}
}// 微信支付
public class WechatPayStrategy implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("微信支付:" + amount + "元");}
}
3. 环境类封装策略调用
public class PaymentContext {private PaymentStrategy strategy;public PaymentContext(PaymentStrategy strategy) {this.strategy = strategy;}public void executePayment(double amount) {strategy.pay(amount);}
}
4. 客户端调用
public class Client {public static void main(String[] args) {PaymentContext context = new PaymentContext(new AlipayStrategy());context.executePayment(100.0); // 输出:支付宝支付:100.0元context = new PaymentContext(new WechatPayStrategy());context.executePayment(200.0); // 输出:微信支付:200.0元}
}
三、项目实践案例:电商促销活动
在电商系统中,促销活动类型多样(如满减、折扣、赠品),不同活动需要动态切换计算逻辑。策略模式可优雅解决这类需求。
1. 业务场景分析
- 需求:根据活动类型计算订单最终价格。
- 痛点:直接使用
if-else判断活动类型会导致代码臃肿,新增活动需修改核心逻辑。
2. 策略模式实现
定义促销策略接口
public interface PromotionStrategy {double applyPromotion(double originalPrice);
}
实现具体促销策略
// 满减策略:满300减50
public class FullReductionStrategy implements PromotionStrategy {@Overridepublic double applyPromotion(double originalPrice) {return originalPrice >= 300 ? originalPrice - 50 : originalPrice;}
}// 折扣策略:8折优惠
public class DiscountStrategy implements PromotionStrategy {@Overridepublic double applyPromotion(double originalPrice) {return originalPrice * 0.8;}
}
环境类封装策略选择
public class PromotionContext {private PromotionStrategy strategy;public void setStrategy(PromotionStrategy strategy) {this.strategy = strategy;}public double calculateFinalPrice(double originalPrice) {return strategy.applyPromotion(originalPrice);}
}
结合工厂模式动态获取策略(增强扩展性)
public class PromotionStrategyFactory {private static final Map<String, PromotionStrategy> strategies = new HashMap<>();static {strategies.put("FULL_REDUCTION", new FullReductionStrategy());strategies.put("DISCOUNT", new DiscountStrategy());}public static PromotionStrategy getStrategy(String promotionType) {return strategies.get(promotionType);}
}
客户端调用示例
public class OrderService {public double calculateOrderPrice(String promotionType, double originalPrice) {PromotionStrategy strategy = PromotionStrategyFactory.getStrategy(promotionType);PromotionContext context = new PromotionContext();context.setStrategy(strategy);return context.calculateFinalPrice(originalPrice);}
}// 测试输出
OrderService service = new OrderService();
System.out.println(service.calculateOrderPrice("FULL_REDUCTION", 350)); // 300.0
System.out.println(service.calculateOrderPrice("DISCOUNT", 200)); // 160.0
四、策略模式的优势与适用场景
优势
- 开闭原则:新增策略无需修改已有代码。
- 消除条件分支:避免
if-else或switch-case的泛滥。 - 算法复用:策略对象可跨模块共享。
适用场景
- 业务规则动态切换:如支付方式、促销活动、风控规则。
- 算法需要独立演化:如排序算法、数据加密方式。
- 隐藏复杂逻辑:如第三方服务调用(不同渠道短信发送)。
五、总结
策略模式通过将算法封装为独立对象,赋予系统高度的灵活性和扩展性。在实际项目中,策略模式常与工厂模式、Spring 容器管理结合,通过依赖注入动态选择策略。但需注意:若策略数量过多,需考虑使用 策略枚举 或 配置中心 统一管理,避免策略类膨胀。
相关文章:
策略模式:优雅应对多变的业务需求
一、策略模式基础概念 策略模式(Strategy Pattern) 是一种行为型设计模式,它通过定义一系列可互换的算法族,并将每个算法封装成独立的策略类,使得算法可以独立于使用它的客户端变化。策略模式的核心思想是 “将算法的…...
SpringBoot企业级开发之【文章分类-新增文章分类】
看一下新增文章的需求: 接口文档: 开发思路: 先在controller下去创建add方法,方法内导入Service类获取add的结果;再在Service接口下去创建add的方法;然后在Service实现类下去实现方法的作用,且导…...
【AI News | 20250421】每日AI进展
AI Repos 1、langgraph-mcp-agents 基于LangGraph的AI智能体系统,集成了MCP,使AI助手能访问各种数据源和API。提供了Streamlit网页界面,方便与LangGraph和MCP工具交互。可以通过界面动态添加、删除以及配置MCP工具,无需重启应用&…...
牛客 | OJ在线编程常见输入输出练习
1.只有输出 言归正传,本张试卷总共包括18个题目,包括了笔试情况下的各种输入输出。 第一题不需要输入,仅需输出字符串 Hello Nowcoder! 即可通过。 #include <iostream> using namespace std; int main(){string s "Hello Nowco…...
python生成动态库在c++中调用
一.Windows下生成动态库.pyd 在setup.py的同目录下使用python setup.py build_ext --inplace 二.在vscode的c中使用.pyd文件(动态库) 1)配置python的环境 python -c "import sys; print(sys.executable)" #确定python安装位置 2…...
程序员学商务英文之Terms of Payment Packing
Dia-3: Packing 1 包装-1 1. I’m here to improve my communication skill of English. 我来这里是为了提升我的英文沟通技能。 2. What a co-incidence! Fancy meeting you here. 这么巧!真没想到在这见到你。 3. Some birds aren’t meant to be caged…...
OpenCV基础函数学习4
【大纲笔记见附件pdf】 目录 一、基于OpenCV的形态学操作 二、基于OpenCV的直方图处理 三、基于OpenCV霍夫变换 四、基于OpenCV模板匹配 一、基于OpenCV的形态学操作 二、基于OpenCV的直方图处理 三、基于OpenCV霍夫变换 四、基于OpenCV模板匹配...
Nginx反向代理用自定义Header参数
【啰嗦两句】 也不知道为啥,我仅仅想在Nginx的反向代理中使用自己定义的“x-api-key”做Header参数,却发现会被忽略,网上搜的资料都是说用“proxy_set_header”,却只愿意介绍最基本的几个参数,你懂的,那些资…...
详解机器学习各算法的优缺点!!
在机器学习这个 “工具库” 里,算法就像各种各样的工具,每一种都有自己的 “脾气” 和 “特长”。有些算法擅长找规律,有些算法能快速分类,还有些在处理复杂数据时特别厉害。 而且,就像锤子适合敲钉子、螺丝刀适合拧螺…...
Manus AI与多语言手写识别
一、手写识别技术的发展历程 1.1 早期的手写识别技术 手写识别技术起源很早,1929年德国人Tausheck就取得了相关专利。早期主要采用模板匹配等方法,该方法需准备字符模板库,提取待识别字符特征后进行匹配。但其局限性明显,对字符…...
C++23 让 Lambda 表达式中的 () 更可选:P1102R2 提案深度解析
文章目录 一、背景与动机:Lambda 表达式中的痛点1.1 问题的根源 二、P1102R2 提案:让 () 可选2.1 提案的核心内容2.2 语法调整的细节2.3 提案的合理性 三、编译器支持:主流编译器的跟进四、对 C 编程的影响:简化语法与提升一致性4…...
规则引擎 - Easy Rules
Easy Rules 依赖demodemo1demo2 总结 Easy Rules 是一个轻量级的 Java 规则引擎,使用简单,适合快速开发和简单的规则场景,适合对于一些判断,是否属于白名单,是否有特殊权限,是否属于当前区域,调…...
3步拆解Linux内核源码的思维模型
3步拆解Linux内核源码的思维模型 ——从“不敢碰”到“庖丁解牛” 一、第一步:资料收集与框架搭建——像拼图一样找到“地图” 初看Linux内核源码的人,往往会被其千万行代码淹没。但正如登山前需要地形图,阅读内核前必须构建认知框架。 1…...
MyBatis与MyBatis-Plus:字段自动填充的两种实现方式
目录 1. 使用 MyBatis 拦截器实现字段自动填充 2. 使用 MyBatis-Plus 实现字段自动填充 1. 使用 MyBatis 拦截器实现字段自动填充 实现步骤 创建拦截器 实现 MyBatis 的 Interceptor 接口,通过拦截 MyBatis 执行的 SQL 操作来自动填充公共字段 Intercepts({Signa…...
深度学习:人工智能的核心驱动力
深度学习 在当今科技飞速发展的时代,人工智能(AI)无疑是最具影响力和变革性的技术之一。而深度学习,作为人工智能领域的核心技术,正以其强大的能力和广泛的应用,深刻地改变着我们的生活和世界。深度学习究竟…...
Java学习路线--自用--带链接
1.Java基础 黑马:黑马程序员Java零基础视频教程_下部 2.MySQL 尚硅谷:MySQL数据库入门到大牛,mysql安装到优化,百科全书级,全网天花板 3.Redis 黑马:黑马程序员Redis入门到实战教程,深度透…...
在Qt中验证LDAP账户(Windows平台)
一、前言 原本以为在Qt(Windows平台)中验证 LDAP 账户很简单:集成Open LDAP的开发库即可。结果临了才发现,Open LDAP压根儿不支持Windows平台。沿着重用的原则,考虑迁移Open LDAP的源代码,却发现工作量不小…...
【sylar-webserver】重构日志系统
文章目录 主要工作流程图FiberConditionBufferBufferManagerLogEvent 序列化 & 反序列化LoggerRotatingFileLogAppender 主要工作 实现, LogEvent 序列化和反序列化 (使用序列化是为了更标准,如果转成最终的日志格式再存储(确…...
树莓派超全系列教程文档--(38)config.txt视频配置
config.txt视频配置 视频选项HDMI模式树莓派4-系列的HDMI树莓派5-系列的HDMI 复合视频模式enable_tvout LCD显示器和触摸屏ignore_lcddisable_touchscreen 通用显示选项disable_fw_kms_setup 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 视频选…...
线性DP:最短编辑距离
Dp 状态表示 f(i,j) 集合所有将A[1~i]变成B[1~j]的操作方式属性min 状态计算 (划分) 增f(i,j)f(i,j-1)1//A[i]元素要增加,说明A前i位置与B前j-1相同删f(i,j)f(i-1,j)1//A[i]元素要删除,说明A前i…...
STM32 HAL库FreeRTOS 中断管理
一、引言 在嵌入式系统开发中,STM32 微控制器凭借其高性能、低功耗和丰富的外设资源,被广泛应用于各种领域。FreeRTOS 作为一款轻量级、开源且功能强大的实时操作系统,为多任务处理提供了良好的支持。中断是嵌入式系统中实现实时响应外部事件…...
STM32——新建工程并使用寄存器以及库函数进行点灯
本文是根据江协科技提供的教学视频所写,旨在便于日后复习,同时供学习嵌入式的朋友们参考,文中涉及到的所有资料也均来源于江协科技(资料下载)。 新建工程并使用寄存器以及库函数进行点灯操作 新建工程步骤1.建立工程2.…...
java集合框架day1————集合体系介绍
在进入正文之前,我们先来思考一下之前学过的数组有什么缺点? <1>长度开始时必须指定,而且一旦指定,不能更改 <2>保存的必须为同一类型的元素 <3>使用数组进行增加/删除元素的代码比较麻烦 为了方便读者理解&…...
百度热力图数据获取,原理,处理及论文应用18
目录 0、数据简介0、示例数据1、百度热力图数据日期如何选择1.1、其他实验数据的时间1.2、看日历天气 2、百度热力图几天够研究?部分文章统计3、数据原理3.1 Bd09mc即百度墨卡托投影坐标系200单位的距离是可以自己设置的吗?3.2 csv文件字段说明3.3 ** 这…...
【区块链技术解析】从原理到实践的全链路指南
目录 前言:技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块技术选型对比 二、实战演示环境配置要求核心代码实现(10个案例)案例1:创建简单区块链案例2:工作…...
【身份证扫描件识别表格】如何识别大量身份证扫描件将内容导出保存到Excel表格,一次性处理多张身份证图片导出Excel表格,基于WPF和腾讯云的实现方案
基于WPF和腾讯云的身份证扫描件批量处理方案 适用场景 本方案适用于需要批量处理大量身份证扫描件的场景,例如: 企业人事部门批量录入新员工身份信息银行或金融机构办理批量开户业务教育机构收集学生身份信息政府部门进行人口信息统计酒店、医院等需要实名登记的场所这些场景…...
可穿戴设备待机功耗需降至μA级但需保持实时响应(2万字长文深度解析)
可穿戴设备的功耗与响应需求之矛盾 在过去十年中,可穿戴设备以惊人的速度融入我们的日常生活,成为现代科技与个人健康管理的重要交汇点。从智能手表到健身手环,从医疗监测设备到增强现实眼镜,这些设备不仅仅是科技产品的延伸&…...
Django视图(未分离)
ListView、DetailView、CreateView、UpdateView 和 DeleteView 是 Django 框架中基于类的通用视图(Class-Based Generic Views) 配置 URL 路由 在 urls.py 中为这些视图配置路由: from django.urls import path from .views import (PostLis…...
[Python] 入门核心笔记
目录 一、Python简介重点 二、编程语言基础重点 三、Python安装重点 四、第一个Python程序重点 五、Python解释器重点 六、Python开发环境重点 一、Python简介重点 起源:1989年Gudio van Rossum开发,1991年诞生,名字源于电视剧《Monty Python…...
计算机视觉与深度学习 | Transformer原理,公式,代码,应用
Transformer 详解 Transformer 是 Google 在 2017 年提出的基于自注意力机制的深度学习模型,彻底改变了序列建模的范式,解决了 RNN 和 LSTM 在长距离依赖和并行计算上的局限性。以下是其原理、公式、代码和应用的详细解析。 一、原理 核心架构 Transformer 由 编码器(Encod…...
