当前位置: 首页 > news >正文

【设计模式】策略模式(政策(Policy)模式)

策略模式(Strategy Pattern)详解


一、策略模式简介

策略模式(Strategy Pattern) 是一种 行为型设计模式(对象行为型模式),它定义了一系列算法,并将每一个算法封装起来,使它们可以互相替换,独立于使用它们的客户端。

又称为政策(Policy)模式
每一个封装算法的类称之为策略(Strategy)类
策略模式提供了一种可插入式(Pluggable)算法的实现方案。

你可以把它理解为:

“一个工具箱里有多个工具,你可以在不同场景下选择不同的工具来完成任务。”

在策略模式中,这些“工具”就是各种具体的策略类,而“任务执行者”则是使用这些策略的对象。

旅游出行方式
在这里插入图片描述
实现某个目标的途径不止一条,可根据实际情况选择一条合适的途径。

软件开发
多种算法,例如排序、查找、打折等
使用硬编码(Hard Coding)实现将导致系统违背开闭原则,扩展性差,且维护困难
可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法 —> 策略类

public class Context
{……public void algorithm(String type)  {......if(type == "strategyA"){//算法A}else if(type == "strategyB"){//算法B}else if(type == "strategyC"){//算法C}......}……
} 

策略模式包含以下3个角色
Context(环境类)
Strategy(抽象策略类)
ConcreteStrategy(具体策略类)

在这里插入图片描述


二、解决的问题类型

策略模式主要用于解决以下问题:

  • 同一行为具有多种实现方式:比如支付方式可以是支付宝、微信、银行卡等。
  • 避免大量的 if-else 或 switch-case 判断逻辑:提高代码可读性和扩展性。
  • 希望在运行时动态切换算法或行为:比如根据用户等级选择不同的折扣策略。

三、使用场景

场景示例
不同支付方式支付宝、微信、银联等
折扣计算普通会员、VIP会员、超级会员等不同折扣规则
物流配送顺丰、京东、德邦等不同物流策略
游戏角色技能角色攻击方式随武器变化而变化

四、核心结构

策略模式通常包含三个部分:

  1. 策略接口(Strategy):定义所有策略共有的行为。
  2. 具体策略类(Concrete Strategies):实现接口中的具体行为。
  3. 上下文类(Context):持有一个策略接口的引用,负责调用策略方法。

五、实际代码案例(Java)

我们以电商系统中的“支付方式”为例,演示策略模式的使用。

1. 定义策略接口

// 支付策略接口
public interface PaymentStrategy {void pay(int amount);
}

2. 实现具体策略类

// 微信支付策略
public class WeChatPay implements PaymentStrategy {@Overridepublic void pay(int amount) {System.out.println("WeChat Pay: $" + amount);}
}// 支付宝支付策略
public class AliPay implements PaymentStrategy {@Overridepublic void pay(int amount) {System.out.println("AliPay: $" + amount);}
}// 银行卡支付策略
public class BankCardPay implements PaymentStrategy {@Overridepublic void pay(int amount) {System.out.println("Bank Card Pay: $" + amount);}
}

3. 创建上下文类

// 上下文类:支付环境
public class ShoppingCart {private PaymentStrategy paymentStrategy;// 设置策略public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}// 使用策略进行支付public void checkout(int amount) {if (paymentStrategy == null) {throw new IllegalStateException("Please select a payment strategy.");}paymentStrategy.pay(amount);}
}

4. 客户端测试类

public class Client {public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();// 使用微信支付cart.setPaymentStrategy(new WeChatPay());cart.checkout(100);// 切换为支付宝支付cart.setPaymentStrategy(new AliPay());cart.checkout(200);// 切换为银行卡支付cart.setPaymentStrategy(new BankCardPay());cart.checkout(300);}
}

输出结果:

WeChat Pay: $100
AliPay: $200
Bank Card Pay: $300

典型代码(C++)

典型的抽象策略类代码

abstract class AbstractStrategy
{public abstract void Algorithm(); //声明抽象算法
}

典型的抽象策略类代码

class ConcreteStrategyA : AbstractStrategy 
{
//算法的具体实现
public override void Algorithm() 
{//算法A
}
}

典型的环境类代码

class Context
{private AbstractStrategy strategy; //维持一个对抽象策略类的引用public void SetStrategy(AbstractStrategy strategy) {this.strategy = strategy;}//调用策略类中的算法public void Algorithm() {strategy.Algorithm();}
}

典型的客户端代码片段

……
Context context = new Context();
AbstractStrategy strategy;
strategy = new ConcreteStrategyA(); //可在运行时指定类型,通过配置文件和反射机制实现
context.SetStrategy(strategy);
context.Algorithm();
……
其他案例
  1. 某软件公司为某电影院开发了一套影院售票系统,在该系统中需要为不同类型的用户提供不同的电影票打折方式,具体打折方案如下:
    (1) 学生凭学生证可享受票价8折优惠。
    (2) 年龄在10周岁及以下的儿童可享受每张票减免10元的优惠(原始票价需大于等于20元)。
    (3) 影院VIP用户除享受票价半价优惠外还可进行积分,积分累计到一定额度可换取电影院赠送的奖品。
    该系统在将来可能还要根据需要引入新的打折方式。现使用策略模式设计该影院售票系统的打折方案

在这里插入图片描述

  1. 排序策略
    某系统提供了一个用于对数组数据进行操作的类,该类封装了对数组的常见操作,如查找数组元素、对数组元素进行排序等。现以排序操作为例,使用策略模式设计该数组操作类,使得客户端可以动态地更换排序算法,可以根据需要选择冒泡排序或选择排序或插入排序,也能够灵活地增加新的排序算法。

在这里插入图片描述

  1. 旅游出行策略
    旅游出行方式可以有多种,如可以乘坐飞机旅游,也可以乘火车旅游,如果有兴趣自行车游也是一种极具乐趣的出行方式。不同的旅游出行方式有不同的实现过程,客户根据自己的需要选择一种合适的旅游方式。在本实例中我们用策略模式来模拟这一过程。

在这里插入图片描述

六、优缺点分析

优点描述
解耦将算法和使用它的对象分离,降低耦合度
易于扩展新增策略只需新增类,符合开闭原则。提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为
运行时可切换策略提供更高的灵活性
减少冗长的条件判断语句替代 if-else 或 switch-case 结构
其他提供了管理相关的算法族的办法,提供了一种可以替换继承关系的办法,提供了一种算法的复用机制,不同的环境类可以方便地复用策略类
缺点描述
增加类数量每个策略对应一个类,可能导致类膨胀,将造成系统产生很多具体策略类
需要对外暴露策略类客户端需了解所有策略才能选择使用哪个
不适合简单分支逻辑如果策略种类很少,使用策略模式反而增加了复杂度
其他无法同时在客户端使用多个策略类

七、与其他模式对比(补充)

模式名称目标
模板方法模式在父类定义算法骨架,子类实现具体步骤
责任链模式请求在链上传递,每个节点决定是否处理请求
策略模式多种算法/行为封装成策略,运行时可切换

八、最终小结

策略模式是一种非常实用的设计模式,适用于那些具有多种实现方式、需要灵活切换的业务逻辑。它通过将行为抽象为接口和实现类,使得程序更加清晰、易维护、易扩展。

在开发电商系统、支付模块、权限控制、游戏逻辑等项目中,策略模式都能发挥重要作用。


📌 一句话总结:

策略模式就像“万能遥控器”,可以自由切换不同的功能模块,让程序更灵活、更具适应性。


推荐使用方式:

  • 对于固定的行为,但实现方式多样的场景优先考虑策略模式;
  • 可结合工厂模式统一创建策略实例,提升管理效率;
  • 使用 Lambda 表达式简化简单策略的实现(如 Java 8+);

部分内容由AI大模型生成,注意识别!

http://www.lryc.cn/news/587330.html

相关文章:

  • Java小白-设计模式
  • Java 接口 剖析
  • 操作系统-第四章存储器管理和第五章设备管理-知识点整理(知识点学习 / 期末复习 / 面试 / 笔试)
  • 什么是渐进式框架
  • 什么时候会用到 concurrent.futures?要不要背?
  • 17.使用DenseNet网络进行Fashion-Mnist分类
  • 2024CVPR:Question Aware Vision Transformer for Multimodal Reasoning介绍
  • Action-Agnostic Point-Level Supervision for Temporal Action Detection
  • 【读书笔记】《Effective Modern C++》第4章 Smart Pointers
  • 从零开始学习深度学习—水果分类之PyQt5App
  • gcc 源码阅读--C语言预处理
  • 深度学习16(对抗生成网络:GAN+自动编码器)
  • 深入理解 Java JVM
  • Java: OracleHelper
  • MYSQL笔记2
  • 线性基学习笔记
  • 查看Linux服务器显卡使用情况的详细教程
  • 【UE教程/进阶】使用Slate
  • 【unitrix】 5.0 第二套类型级二进制数基本结构体(types2.rs)
  • SQL预编译:安全高效数据库操作的关键
  • 苍穹外卖Day3
  • markdown-it-mathjax3-pro —— 新一代 Markdown 数学公式渲染插件
  • vue的优缺点
  • 框架和库的区别
  • day16~17-系统负载高故障与磁盘管理
  • muduo概述
  • 电商系统未来三年趋势:体验升级、技术赋能与模式重构
  • ASP.NET Core 中的延迟注入:原理与实践
  • 【UE教程/进阶】UE中的指针与引用
  • 应用层协议和JSON的使用