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

设计模式基础概念(行为模式):策略模式

概述

策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换

主要目的是通过定义相似的算法,替换if else 语句写法,并且可以随时相互替换

结构

在这里插入图片描述

示例

策略模式在 Java 代码中很常见。 它经常在各种框架中使用, 能在不扩展类的情况下向用户提供改变其行为的方式。

javax.servlet.http.HttpServlet: ​ service­()方法, 还有所有接受 Http­Servlet­Request和 Http­Servlet­Response对象作为参数的 do­XXX()方法。

识别方法: 策略模式可以 通过允许嵌套对象完成实际工作的方法,以及允许将该对象替换为不同对象的设置器来识别。

伪代码实现

strategies

策略(strategies)的定义:所有具体策略的通用接口, 它声明了一个上下文用于执行策略的方法

public interface PayStrategy {boolean pay(int paymentAmount);void collectPaymentDetails();
}

Concrete Strategies

具体策略 (Concrete Strategies): 实现上下文所用算法的各种不同变体。

PayByPayPal: 使用 PayPal 支付

public class PayByPayPal implements PayStrategy {@Overridepublic void collectPaymentDetails() {// todo}@Overridepublic boolean pay(int paymentAmount) {// todo}

PayByCreditCard: 使用信用卡支付

public class PayByCreditCard implements PayStrategy {@Overridepublic void collectPaymentDetails() {// todo}@Overridepublic boolean pay(int paymentAmount) {// todo}

Context

上下文 (Context): 维护指向具体策略的引用, 且仅通过策略接口与该对象进行交流。

public class Order {private int totalCost = 0;private boolean isClosed = false;// 提供一个计算的接口供客户端使用。public void processOrder(PayStrategy strategy) {strategy.collectPaymentDetails();// Here we could collect and store payment data from the strategy.}}

Client

客户端 (Client) 会创建一个特定策略对象并将其传递给上下文。

上下文则会提供一个设置器以便客户端在运行时替换相关联的策略。

public class Client {private static Map<Integer, Integer> priceOnProducts = new HashMap<>();private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));private static Order order = new Order();private static PayStrategy strategy;static {priceOnProducts.put(1, 2200);priceOnProducts.put(2, 1850);priceOnProducts.put(3, 1100);priceOnProducts.put(4, 890);}public static void main(String[] args) throws IOException {while (!order.isClosed()) {int cost;String continueChoice;do {System.out.print("Please, select a product:" + "\n" +"1 - Mother board" + "\n" +"2 - CPU" + "\n" +"3 - HDD" + "\n" +"4 - Memory" + "\n");int choice = Integer.parseInt(reader.readLine());cost = priceOnProducts.get(choice);System.out.print("Count: ");int count = Integer.parseInt(reader.readLine());order.setTotalCost(cost * count);System.out.print("Do you wish to continue selecting products? Y/N: ");continueChoice = reader.readLine();} while (continueChoice.equalsIgnoreCase("Y"));if (strategy == null) {System.out.println("Please, select a payment method:" + "\n" +"1 - PalPay" + "\n" +"2 - Credit Card");String paymentMethod = reader.readLine();// Client creates different strategies based on input from user,// application configuration, etc.if (paymentMethod.equals("1")) {strategy = new PayByPayPal();} else {strategy = new PayByCreditCard();}}// Order object delegates gathering payment data to strategy object,// since only strategies know what data they need to process a// payment.order.processOrder(strategy);System.out.print("Pay " + order.getTotalCost() + " units or Continue shopping? P/C: ");String proceed = reader.readLine();if (proceed.equalsIgnoreCase("P")) {// Finally, strategy handles the payment.if (strategy.pay(order.getTotalCost())) {System.out.println("Payment has been successful.");} else {System.out.println("FAIL! Please, check your data.");}order.setClosed();}}}
}

应用场景

当你想使用对象中各种不同的算法变体, 并希望能在运行时切换算法时, 可使用策略模式。

策略模式让你能够将对象关联至可以不同方式执行特定子任务的不同子对象, 从而以间接方式在运行时更改对象行为。

当你有许多仅在执行某些行为时略有不同的相似类时, 可使用策略模式。

策略模式让你能将不同行为抽取到一个独立类层次结构中, 并将原始类组合成同一个, 从而减少重复代码。

如果算法在上下文的逻辑中不是特别重要, 使用该模式能将类的业务逻辑与其算法实现细节隔离开来。

策略模式让你能将各种算法的代码、 内部数据和依赖关系与其他代码隔离开来。 不同客户端可通过一个简单接口执行算法, 并能在运行时进行切换。

当类中使用了复杂条件运算符以在同一算法的不同变体中切换时, 可使用该模式。

策略模式将所有继承自同样接口的算法抽取到独立类中, 因此不再需要条件语句。 原始对象并不实现所有算法的变体, 而是将执行工作委派给其中的一个独立算法对象。

实现步骤

首先,从上下文类中找出修改频率较高的算法

其次,声明该算法所有变体的通用策略接口。将算法逐一抽取到各自的类中, 它们都必须实现策略接口。

之后,在上下文类中添加一个成员变量用于保存对于策略对象的引用

  • 然后提供设置器以修改该成员变量。
  • 上下文仅可通过策略接口同策略对象进行交互,
  • 如有需要还可定义一个接口来让策略访问其数据。

最后,客户端必须将上下文类与相应策略进行关联, 使上下文可以预期的方式完成其主要工作。

优缺点

策略模式优点:

  • 扩展性好,可以在不修改对象结构的情况下,为新的算法进行添加新的类进行实现;
  • 灵活性好,可以对算法进行自由切换;

策略模式缺点:

  • 使用策略类变多,会增加系统的复杂度。;
  • 客户端必须知道所有的策略类才能进行调用;
http://www.xdnf.cn/news/1298863.html

相关文章:

  • c/c++实现 TCP Socket网络通信
  • ASCII与Unicode:编码世界的奥秘
  • 阿里云TranslateGeneral - 机器翻译SDK-自己封账单文件版本—仙盟创梦IDE
  • 机器学习实战篇--TF-IDF实战--名著红楼梦的文本数据处理
  • 亚马逊品牌权力重构:第三方卖家崛起下的竞争生态与系统性应对框架
  • 微信公众号推送文字消息与模板消息
  • 加密货币交易所开发:如何打造安全、高并发的数字资产交易平台?
  • 开源安全云盘存储:Hoodik 实现端到端数据加密,Docker快速搭建
  • 深度学习-卷积神经网络CNN-膨胀卷积、可分离卷积(空间可分离、深度可分离)、分组卷积
  • 【保姆级教程】CentOS 7 部署 FastDFS 全流程(避坑指南)
  • 具身智能Scaling Law缺失:机器人界的“摩尔定律“何时诞生?
  • CVPR 2025 | 机器人操控 | RoboGround:用“掩码”中介表示,让机器人跨场景泛化更聪明
  • 3D商品展示:技术狂欢下的普及困局
  • DataHub OPC Gateway:实现OPC UA与OPC DA无缝集成的高性能网关
  • 【代码随想录day 20】 力扣 108.将有序数组转换为二叉搜索树
  • 京东【自主售后】物流信息获取_影刀RPA源码解读
  • Docker部署美化SunPanel导航页
  • python+vue扫盲
  • anaconda创建pytorch1.10.0和pytorch2.0.0的GPU环境
  • java:创建指定容器类型(如ImmutableSet)的Collector对象
  • Redis (REmote DIctionary Server) 高性能数据库
  • 设计模式笔记_行为型_状态模式
  • OpenAI 的浏览器将使用 ChatGPT Agent 来控制浏览器
  • 记录一些奇奇怪怪的面试题
  • 【慕伏白】CTFHub 技能树学习笔记 -- 基础知识 签到
  • AI 编程实践:用 Trae 快速开发 HTML 贪吃蛇游戏
  • 【软考中级网络工程师】知识点之常用网络诊断和配置命令
  • 机器学习核心概念与实践笔记
  • 解刨HashMap的put流程 <二> JDK 1.8
  • Redis 03 redis 缓存异常