策略模式:优雅应对多变的业务需求

news2025/4/22 9:49:02
一、策略模式基础概念

策略模式(Strategy Pattern) 是一种行为型设计模式,它通过定义一系列可互换的算法族,并将每个算法封装成独立的策略类,使得算法可以独立于使用它的客户端变化。策略模式的核心思想是 “将算法的定义与使用分离”,从而解决在复杂业务场景中因条件分支过多导致的代码臃肿、维护困难等问题。

核心角色
  1. 环境类(Context):持有策略对象的引用,负责调用具体策略。
  2. 抽象策略(Strategy):定义算法接口,声明策略方法的规范。
  3. 具体策略(Concrete Strategy):实现抽象策略接口,提供具体的算法实现。

二、简单案例:支付方式选择

假设需要实现一个支持多种支付方式的系统(支付宝、微信、银行卡),通过策略模式可以灵活扩展支付方式,避免冗长的 if-else 判断。

1. 定义抽象策略接口
public interface PaymentStrategy {
    void pay(double amount);
}
2. 实现具体策略类
// 支付宝支付
public class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("支付宝支付:" + amount + "元");
    }
}

// 微信支付
public class WechatPayStrategy implements PaymentStrategy {
    @Override
    public 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 {
    @Override
    public double applyPromotion(double originalPrice) {
        return originalPrice >= 300 ? originalPrice - 50 : originalPrice;
    }
}

// 折扣策略:8折优惠
public class DiscountStrategy implements PromotionStrategy {
    @Override
    public 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-elseswitch-case 的泛滥。
  • 算法复用:策略对象可跨模块共享。
适用场景
  1. 业务规则动态切换:如支付方式、促销活动、风控规则。
  2. 算法需要独立演化:如排序算法、数据加密方式。
  3. 隐藏复杂逻辑:如第三方服务调用(不同渠道短信发送)。

五、总结

策略模式通过将算法封装为独立对象,赋予系统高度的灵活性和扩展性。在实际项目中,策略模式常与工厂模式、Spring 容器管理结合,通过依赖注入动态选择策略。但需注意:若策略数量过多,需考虑使用 策略枚举配置中心 统一管理,避免策略类膨胀。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2340018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot企业级开发之【文章分类-新增文章分类】

看一下新增文章的需求&#xff1a; 接口文档&#xff1a; 开发思路&#xff1a; 先在controller下去创建add方法&#xff0c;方法内导入Service类获取add的结果&#xff1b;再在Service接口下去创建add的方法&#xff1b;然后在Service实现类下去实现方法的作用&#xff0c;且导…

【AI News | 20250421】每日AI进展

AI Repos 1、langgraph-mcp-agents 基于LangGraph的AI智能体系统&#xff0c;集成了MCP&#xff0c;使AI助手能访问各种数据源和API。提供了Streamlit网页界面&#xff0c;方便与LangGraph和MCP工具交互。可以通过界面动态添加、删除以及配置MCP工具&#xff0c;无需重启应用&…

牛客 | OJ在线编程常见输入输出练习

1.只有输出 言归正传&#xff0c;本张试卷总共包括18个题目&#xff0c;包括了笔试情况下的各种输入输出。 第一题不需要输入&#xff0c;仅需输出字符串 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文件&#xff08;动态库&#xff09; 1&#xff09;配置python的环境 python -c "import sys; print(sys.executable)" #确定python安装位置 2…

OpenCV基础函数学习4

【大纲笔记见附件pdf】 目录 一、基于OpenCV的形态学操作 二、基于OpenCV的直方图处理 三、基于OpenCV霍夫变换 四、基于OpenCV模板匹配 一、基于OpenCV的形态学操作 二、基于OpenCV的直方图处理 三、基于OpenCV霍夫变换 四、基于OpenCV模板匹配

Nginx反向代理用自定义Header参数

【啰嗦两句】 也不知道为啥&#xff0c;我仅仅想在Nginx的反向代理中使用自己定义的“x-api-key”做Header参数&#xff0c;却发现会被忽略&#xff0c;网上搜的资料都是说用“proxy_set_header”&#xff0c;却只愿意介绍最基本的几个参数&#xff0c;你懂的&#xff0c;那些资…

详解机器学习各算法的优缺点!!

在机器学习这个 “工具库” 里&#xff0c;算法就像各种各样的工具&#xff0c;每一种都有自己的 “脾气” 和 “特长”。有些算法擅长找规律&#xff0c;有些算法能快速分类&#xff0c;还有些在处理复杂数据时特别厉害。 而且&#xff0c;就像锤子适合敲钉子、螺丝刀适合拧螺…

C++23 让 Lambda 表达式中的 () 更可选:P1102R2 提案深度解析

文章目录 一、背景与动机&#xff1a;Lambda 表达式中的痛点1.1 问题的根源 二、P1102R2 提案&#xff1a;让 () 可选2.1 提案的核心内容2.2 语法调整的细节2.3 提案的合理性 三、编译器支持&#xff1a;主流编译器的跟进四、对 C 编程的影响&#xff1a;简化语法与提升一致性4…

在Qt中验证LDAP账户(Windows平台)

一、前言 原本以为在Qt&#xff08;Windows平台&#xff09;中验证 LDAP 账户很简单&#xff1a;集成Open LDAP的开发库即可。结果临了才发现&#xff0c;Open LDAP压根儿不支持Windows平台。沿着重用的原则&#xff0c;考虑迁移Open LDAP的源代码&#xff0c;却发现工作量不小…

【sylar-webserver】重构日志系统

文章目录 主要工作流程图FiberConditionBufferBufferManagerLogEvent 序列化 & 反序列化LoggerRotatingFileLogAppender 主要工作 实现&#xff0c; LogEvent 序列化和反序列化 &#xff08;使用序列化是为了更标准&#xff0c;如果转成最终的日志格式再存储&#xff08;确…

树莓派超全系列教程文档--(38)config.txt视频配置

config.txt视频配置 视频选项HDMI模式树莓派4-系列的HDMI树莓派5-系列的HDMI 复合视频模式enable_tvout LCD显示器和触摸屏ignore_lcddisable_touchscreen 通用显示选项disable_fw_kms_setup 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 视频选…

线性DP:最短编辑距离

Dp 状态表示 f&#xff08;i&#xff0c;j&#xff09; 集合所有将A[1~i]变成B[1~j]的操作方式属性min 状态计算 &#xff08;划分&#xff09; 增f(i,j)f(i,j-1)1//A[i]元素要增加&#xff0c;说明A前i位置与B前j-1相同删f(i,j)f(i-1,j)1//A[i]元素要删除&#xff0c;说明A前i…

STM32——新建工程并使用寄存器以及库函数进行点灯

本文是根据江协科技提供的教学视频所写&#xff0c;旨在便于日后复习&#xff0c;同时供学习嵌入式的朋友们参考&#xff0c;文中涉及到的所有资料也均来源于江协科技&#xff08;资料下载&#xff09;。 新建工程并使用寄存器以及库函数进行点灯操作 新建工程步骤1.建立工程2.…

java集合框架day1————集合体系介绍

在进入正文之前&#xff0c;我们先来思考一下之前学过的数组有什么缺点&#xff1f; <1>长度开始时必须指定&#xff0c;而且一旦指定&#xff0c;不能更改 <2>保存的必须为同一类型的元素 <3>使用数组进行增加/删除元素的代码比较麻烦 为了方便读者理解&…

百度热力图数据获取,原理,处理及论文应用18

目录 0、数据简介0、示例数据1、百度热力图数据日期如何选择1.1、其他实验数据的时间1.2、看日历天气 2、百度热力图几天够研究&#xff1f;部分文章统计3、数据原理3.1 Bd09mc即百度墨卡托投影坐标系200单位的距离是可以自己设置的吗&#xff1f;3.2 csv文件字段说明3.3 ** 这…

【身份证扫描件识别表格】如何识别大量身份证扫描件将内容导出保存到Excel表格,一次性处理多张身份证图片导出Excel表格,基于WPF和腾讯云的实现方案

基于WPF和腾讯云的身份证扫描件批量处理方案 适用场景 本方案适用于需要批量处理大量身份证扫描件的场景,例如: 企业人事部门批量录入新员工身份信息银行或金融机构办理批量开户业务教育机构收集学生身份信息政府部门进行人口信息统计酒店、医院等需要实名登记的场所这些场景…

基于语义网络表示的不确定性推理

前文我们已经了解了: 1.不确定与非单调推理的基本概念:不确定与非单调推理的基本概念-CSDN博客 2.不确定与非单调推理的概率方法:不确定与非单调推理的概率方法-CSDN博客 3.不确定与非单调推理的可信度方法:不确定与非单调推理的可信度方法-CSDN博客 4.不确定与非单调推…

ICMAN防水触摸芯片 - 复杂环境下精准交互,提升触控体验

▍核心优势 ◆ 超强抗干扰能力 ◆ 工业级设计&#xff0c;一致性和稳定性好 ▍提供场景化解决方案 【智能厨电矩阵】抽油烟机档位调节 | 电磁炉火力触控 | 洗碗机模式切换 【卫浴设备方案】淋浴房雾化玻璃控制 | 智能马桶触控面板 | 浴缸水位感应 【工业控制应用】仪器仪…

【java实现+4种变体完整例子】排序算法中【希尔排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是希尔排序的详细解析&#xff0c;包含基础实现、常见变体的完整代码示例&#xff0c;以及各变体的对比表格&#xff1a; 一、希尔排序基础实现 原理 希尔排序是插入排序的改进版本&#xff0c;通过分步缩小增量间隔&#xff0c;将数组分成多个子序列进行插入排序&#…

matlab 处理海洋数据并画图的工具包--ocean_data_tools

matlab 处理海洋数据并画图的工具包–ocean_data_tools matlab 处理海洋数据并画图的工具包–ocean_data_tools ocean_data_tools 简化了提取、格式化和可视化免费可用的海洋学数据的过程。虽然可以在线访问大量海洋学数据&#xff0c;但由于获取这些数据并将其格式化为可用数据…