【设计模式】行为型-策略模式

在这里插入图片描述

策略模式,如春风吹过,随心所欲,变幻无穷,每一丝风都是一种选择。

文章目录

  • 一、订单处理
  • 二、策略模式
  • 三、策略模式的核心组成
  • 四、运用策略模式
  • 五、策略模式的应用场景
  • 六、小结
  • 推荐阅读

一、订单处理

场景假设:有一个订单处理系统,需要根据不同的订单类型(如普通订单、VIP 订单、超级 VIP 订单)来计算订单的折扣金额。

class OrderProcessor {public double calculateDiscount(Order order) {double originalPrice = order.getTotalPrice();double discount = 0.0;if (order.getType() == OrderType.REGULAR) {// 正常订单折扣计算discount = originalPrice * 0.1;} else if (order.getType() == OrderType.VIP) {// VIP 订单折扣计算discount = originalPrice * 0.2;} else if (order.getType() == OrderType.SUPER_VIP) {// 超级 VIP 订单折扣计算discount = originalPrice * 0.3;} // ... 更多订单类型return discount;}
}

上面的代码虽然能够实现需求,但存在以下问题:

  1. 可扩展性差:如果需要添加更多的订单类型,我们必须修改原有的代码,违反了开放-封闭原则。
  2. 代码重复:不同订单类型的折扣计算逻辑被硬编码在同一个方法中,导致代码重复。

二、策略模式

策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时选择算法的行为。在策略模式中,可以定义一系列的算法,把它们封装起来,并且使它们可以互相替换。这样,客户端在使用算法时可以根据需求动态地选择其中一种算法,而不需要更改其代码。

三、策略模式的核心组成

策略模式的核心组成部分包括以下几个要素:

  1. 策略接口(Strategy Interface):这是一个接口或抽象类,定义所有具体策略类必须实现的方法。策略接口通常会声明一个或多个方法,用于执行具体的算法或操作。
  2. 具体策略类(Concrete Strategies):这些类实现了策略接口,每个具体策略类都代表一个独立的算法或操作。它们实现了策略接口中定义的方法,提供了算法的具体实现。
  3. 上下文(Context):上下文类持有一个策略接口的引用,通常会包含一个设置策略的方法,用于动态地切换不同的具体策略。上下文类通过策略接口与具体策略类进行交互,根据需要调用具体策略类的方法。
  4. 客户端(Client):客户端是使用策略模式的类或模块。它通过实例化上下文对象,并设置具体策略类来使用相应的算法或操作。

在这里插入图片描述

这个类图展示了策略模式的核心组成部分:

  • Strategy 接口定义了所有具体策略类必须实现的算法方法 algorithm()
  • ConcreteStrategyA ConcreteStrategyB 是具体的策略类,实现了 Strategy 接口,分别提供了不同的算法实现。
  • Context 类持有一个 Strategy 接口的引用,在运行时可以动态地切换具体的策略。它提供了一个 setStrategy() 方法来设置当前的策略,并且通过 contextInterface() 方法调用当前策略的算法。

四、运用策略模式

场景假设:有一个订单处理系统,需要根据不同的订单类型(如普通订单、VIP 订单、超级 VIP 订单)来计算订单的折扣金额。

  1. 定义抽象策略接口:首先,我们需要定义一个抽象策略接口,该接口包含一个计算折扣价格的方法。这个接口将作为不同折扣策略的基类。

    // 抽象策略接口
    interface DiscountStrategy {double calculateDiscount(double originalPrice);
    }
    
  2. 创建具体策略类:接下来,我们为不同的折扣方式创建具体策略类。每个具体策略类都实现了折扣策略接口,并提供了自己的折扣计算逻辑。

    // 正常折扣策略
    class RegularDiscountStrategy implements DiscountStrategy {@Overridepublic double calculateDiscount(double originalPrice) {// 根据正常折扣计算折后价格return originalPrice * 0.9;}
    }// VIP 折扣策略
    class VIPDiscountStrategy implements DiscountStrategy {@Overridepublic double calculateDiscount(double originalPrice) {// VIP 折扣计算return originalPrice * 0.8;}
    }// 超级 VIP 折扣策略
    class SuperVIPDiscountStrategy implements DiscountStrategy {@Overridepublic double calculateDiscount(double originalPrice) {// 超级 VIP 折扣计算return originalPrice * 0.7;}
    }
    
  3. 创建环境类:我们需要一个环境类来持有策略对象,并根据客户端的选择来执行相应的策略。

    // 环境类
    class OrderProcessor {private DiscountStrategy discountStrategy;public void setDiscountStrategy(DiscountStrategy strategy) {this.discountStrategy = strategy;}public double calculateDiscountedPrice(double originalPrice) {return discountStrategy.calculateDiscount(originalPrice);}
    }
    
  4. 客户端代码:在客户端代码中,我们可以根据订单类型选择不同的折扣策略。

    public class Client {public static void main(String[] args) {OrderProcessor orderProcessor = new OrderProcessor();// 选择不同的折扣策略orderProcessor.setDiscountStrategy(new RegularDiscountStrategy());double discountedPrice1 = orderProcessor.calculateDiscountedPrice(100.0);System.out.println("正常折扣后价格:" + discountedPrice1);orderProcessor.setDiscountStrategy(new VIPDiscountStrategy());double discountedPrice2 = orderProcessor.calculateDiscountedPrice(100.0);System.out.println("VIP 折扣后价格:" + discountedPrice2);}
    }
    

五、策略模式的应用场景

策略模式常见于以下场景:

  1. 行为切换:当系统中有多个类,这些类之间的区别仅在于它们的行为不同时,可以使用策略模式。通过策略模式,用户对象可以在这些行为中动态地选择一个,将不同的行为封装到不同的类中,每个行为对应一种策略。
  2. 算法选择:如果系统中需要在几种算法中动态地选择一种,策略模式也适用。例如,计算方式可以有不同的实现,比如加法策略和乘法策略,用户可以根据需要选择不同的策略。

六、小结

策略模式是一种简单但非常实用的设计模式,它能有效地管理算法的选择和切换,提高系统的灵活性和可维护性。在面对需要动态选择算法或行为的问题时,策略模式是一个值得考虑的解决方案。

推荐阅读

  1. Spring 三级缓存
  2. 深入了解 MyBatis 插件:定制化你的持久层框架
  3. Zookeeper 注册中心:单机部署
  4. 【JavaScript】探索 JavaScript 中的解构赋值
  5. 深入理解 JavaScript 中的 Promise、async 和 await

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

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

相关文章

MySQL高级-索引-设计原则小结

文章目录 1、设计原则2、索引小结2.1、索引概述2.2、索引结构2.3、索引分类2.4、索引语法2.5、SQL性能分析2.6、索引使用2.7、索引设计原则 1、设计原则 针对于数据量较大,且查询比较频繁的表建立索引。针对于常作为查询条件(where)、排序&am…

2毛钱的SOT23-5封装28V、1.5A、1.2MHz DCDC转换器用于LCD偏置电源和白光LED驱动等MT3540升压芯片

前言 之前发了一个TI的BOOST升压芯片,用于LCD偏置电压或LED驱动,请访问以下链接。 6毛钱SOT-23封装28V、400mA 开关升压转换器,LCD偏置电源和白光LED应用芯片TPS61040 国产半导体厂家发展迅猛,今天推荐一个公司带“航天”的升压…

Java基础知识整理笔记

目录 1.关于Java概念 1.1 谈谈对Java的理解? 1.2 Java的基础数据类型? 1.3 关于面向对象的设计理解 1.3.1 面向对象的特性有哪些? 1.3.2 重写和重载的区别? 1.3.3 面向对象的设计原则是什么? 1.4 关于变量与方…

187. 导弹防御系统

Powered by:NEFU AB-IN Link 文章目录 187. 导弹防御系统题意思路代码 187. 导弹防御系统 题意 为了对抗附近恶意国家的威胁,R国更新了他们的导弹防御系统。 一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。 例如,一套系…

代码随想录算法训练营第五十天 | 1143.最长公共子序列、1035.不相交的线、53. 最大子序和、392.判断子序复习

1143.最长公共子序列 题目链接:https://leetcode.cn/problems/longest-common-subsequence/ 文档讲解:https://programmercarl.com/1143.%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1… 视频讲解:https://www.bilibili.com/video/BV1ye4y1L7CQ 最近…

swagger访问路径

Swagger 2.x 版本 访问地址:http://{ip}:{port}/{context-path}/swagger-ui.html {ip} 是你的服务器IP地址。 {port} 是你的应用服务端口,通常为8080。 {context-path} 是你的应用上下文路径,如果应用部署在根路径下,则为空。 …

搭建 MySQL MHA

搭建 MySQL MHA 搭建 MySQL MHA实验拓扑图实验环境实验思路MHA架构故障模拟 实验部署数据库安装主从复制部署时间同步主服务器配置从服务器配置创建链接 MHA搭建安装依赖的环境安装 node 组件安装 manager 组件配置无密码认证在 manager 节点上配置 MHA管理 mysql 节点服务器创…

Spring Cloud Alibaba之网关组件Gateway

实例演示1:在微服务体系中引入GateWay组件 创建一个ServiceForGateway的SpringBoot项目,通过在控制类编写方法对外提供服务 RestController public class Controller {RequestMapping("/getAccount/{id}")public String getAccount(PathVaria…

面试突击:Java 集合知识体系梳理

本文已收录于:https://github.com/danmuking/all-in-one(持续更新) 前言 哈喽,大家好,我是 DanMu。在 Java 开发中,集合类对象绝对是被使用最频繁的对象之一。因此,深入了解集合类对象的底层数…

热敏晶振:成本效益的选择与温补晶振的比较

在精密电子系统的设计中,晶振作为时间基准源,其频率稳定性直接影响到整个系统的性能。其中,温补晶振(Temperature Compensated Crystal Oscillator,简称TCXO)与热敏晶振(Thermistor Compensated Crystal Oscillator)作为在特殊温度…

面试-java异常体系

1.java异常体系 error类是指与jvm相关的问题。如系统崩溃,虚拟机错误,内存空间不足。 非runtime异常不处理,程序就没有办法执行。 一旦遇到异常抛出,后面的异常就不会进行。 (1)常见的error以及exception 2.java异常要点分析…

kubekey 安装高可用 kubernetes 集群

1. 准备环境 1.1 机器准备 4 台机器,操作系统:Ubuntu 24.04/RHEL8/CentOS9 10.111.3.53 master1 10.111.3.54 master2 10.111.3.55 master3 10.111.3.57 node41.2 安装依赖和配置 所有节点都需要执行: Ubuntu: apt-get install -y soca…

[Docker] Ubuntu安装Home Assistant

本文主要记载一些Ubuntu安装Home Assistant的细节,方便后面重装。 1. 安装Docker 安装依赖 $ sudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-common添加 Docker 官方 GPG 密钥 $ curl -fsSL https://mirrors.ustc…

【AI大模型】Transformers大模型库(十四):Datasets Viewer

目录 一、引言 二、Datasets Viewer数据查看器 2.1 概述 2.2 示例 三、总结 一、引言 这里的Transformers指的是huggingface开发的大模型库,为huggingface上数以万计的预训练大模型提供预测、训练等服务。 🤗 Transformers 提供了数以千计的预训练…

如何使用大模型进行文本分类任务?

暑期实习基本结束了,校招即将开启。 不同以往的是,当前职场环境已不再是那个双向奔赴时代了。求职者在变多,HC 在变少,岗位要求还更高了。 最近,我们又陆续整理了很多大厂的面试题,帮助一些球友解惑答疑&…

光遮断器的检测

引脚判别 在检测光遮断器时,先检测出发光二极管的引脚。万用表选择R1k挡,测量光电耦合器任意两个引脚之间的电阻,当出现阻值小时,黑表笔接的为发光二极管的正极,红表笔接的为负极,剩余两极为光敏管的引脚。…

openlayer 鼠标点击船舶,打开船舶简单弹框

背景: 对创建的地图对象,可以添加上监听事件,常用的有:地图点击事件、鼠标移动事件。 通过监听这些事件,又可以区分不同图层的不同要素,获取不同数据; 根据这些数据,又可以发起网络请…

【介绍下SCSS的基本使用】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

微服务应用与开发知识点练习【Nacos、Ribbon、Sentinel】

1.微服务架构的主要优势是什么?( ) A.简化开发过程 B.提高单体应用的性能 C.允许各个服务独立开发、部署和扩展 D.减少代码量 2. 在Spring Boot项目中,配置文件的默认名称是什么?( ) A. co…

React的Props、生命周期

Props 的只读性 “Props” 是 React 中用于传递数据给组件的一种机制,通常作为组件的参数进行传递。在 React 中,props 是只读的,意味着一旦将数据传递给组件的 props,组件就不能直接修改这些 props 的值。所以组件无论是使用函数…