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

news2024/12/26 0:53:41

在这里插入图片描述

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

文章目录

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

一、订单处理

场景假设:有一个订单处理系统,需要根据不同的订单类型(如普通订单、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 {
        @Override
        public double calculateDiscount(double originalPrice) {
            // 根据正常折扣计算折后价格
            return originalPrice * 0.9;
        }
    }
    
    // VIP 折扣策略
    class VIPDiscountStrategy implements DiscountStrategy {
        @Override
        public double calculateDiscount(double originalPrice) {
            // VIP 折扣计算
            return originalPrice * 0.8;
        }
    }
    
    // 超级 VIP 折扣策略
    class SuperVIPDiscountStrategy implements DiscountStrategy {
        @Override
        public 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.coloradmin.cn/o/1871281.html

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

相关文章

Python网络爬虫实战6—下一页,模拟用户点击,切换窗口

【前期提要】感兴趣的可以看看往期文章哈~ Python网络爬虫5-实战网页爬取 Python网络爬虫4-实战爬取pdf Pyhon网络爬虫3-模拟用户点击 Python网络爬虫实战2-下载url下的pdf Python网络爬虫基础1 1.需求背景 针对长虹美菱电器说明书网页形式,编写爬虫代码&#xff…

数通云网架构师涨薪班毕业都有哪些工作企业和岗位?

数通云网架构师涨薪班课程学完后,学员具备全行业全场景交付数通项目的能力,胜任企业网,广域网,数据中心网络等各种网络项目的交付能力,技术能力一项能够匹配年薪达30w-40w以上网络工程师岗位。 与誉天进行人才培养&…

Swagger2及常用校验注释说明

Api(value "后台用户管理") RestController RequestMapping("bossuser") public class BossUserController {ApiOperation(value "测试接口")PostMapping("test")public String testUser(Valid RequestBody TestUser user) {LOG.inf…

大数据------额外软件、插件及技术------Linux(完整知识点汇总)

Linxu 不同领域的主流操作系统 桌面操作系统 WindowsMAac OSLinux 服务器端操作系统 UNIX(付费)LinuxWindows Server(付费) 移动设备操作系统 Android(基于Linux开源)IOS(不开源) 嵌…

电脑桌面便签怎么添加,桌面备忘录软件哪个简单又好用?

在日常的工作或学习中,我们经常需要记事、备忘。这时,一个简单实用的桌面便签工具就显得尤为重要了。那么,电脑桌面便签怎么添加?又有哪些桌面备忘录软件既简单又好用呢? 首先,关于如何添加电脑桌面便签。…

vue如何引入图标

方法1&#xff1a;iconify/vue pnpm add iconify/vue -D 网址&#xff1a;https://icon-sets.iconify.design/ 使用哪个需要安装 如下截图,安装指令&#xff1a; > npm install iconify/icons-gg在使用的页面引入 import { Icon } from “iconify/vue”; <template>…

CODESYS+EtherCAT+X86/ARM硬件平台:高性能运动控制的标配,支持定制

支持的硬件标准与定制平台&#xff1a; X86:INTEL ARM: RK3568/RK3588/TI/NXP/树莓派/全志T3/A40i等 前段时间分享了施耐德基于CODEYS开发的首款支持EtherCAT总线的运动控制器&#xff0c;CODESYSEtherCATX86硬件平台&#xff1a;高性能运动控制的标配。 CODESYS第一次接触还…

【银河麒麟】unzip程序卡住,处理机制详解,附代码

1.服务器环境以及配置 【机型】 处理器&#xff1a; HUAWEI,Kunpeng 920 内存&#xff1a; 400G 【内核版本】 4.19.90-23.18.v2101.ky10.aarch64 【OS镜像版本】 银河麒麟高级服务器操作系统V10-SP1-0711-arm 【第三方软件】 docker 2.问题现象描述 一台k8s服务器…

Camera2内存泄漏修复

最近公司想要使用Camera2来替换线上的旧版相机&#xff0c;功能调研过程中发现Camera2在很多机器上都会有奇怪的内存泄漏&#xff0c;比较明显的时候可能有100M&#xff0c;比较常见的是表现为内存释放不及时&#xff08;上涨一段时间后会有一次下降&#xff09;&#xff0c;这…

Web渗透:XXE-XML外部实体漏洞

XML External Entity (XXE) 漏洞是一种注入攻击&#xff0c;利用不安全的XML解析器来执行各种恶意操作&#xff0c;如读取本地文件、执行远程代码、发起拒绝服务攻击等&#xff1b;此漏洞的根本原因在于XML标准允许在文档中定义外部实体&#xff0c;并在解析时进行解析和替换。…

快储存,分布式文件系统,对象储存

Ceph块存储 镜像快照 快照可以保存某一时间点时的状态数据快照是映像在特定时间点的只读逻辑副本希望回到以前的一个状态&#xff0c;可以恢复快照使用镜像、快照综合示例 rbd create img1 --size 10G 创建镜像rbd ls 查看镜像 rbd info img1 #查看…

使用原子子表创建可重用的子组件

原子子表是一个图形对象&#xff0c;可帮助您在Stateflow图表中创建独立的子部件。原子子表允许&#xff1a; 对具有多个状态或层次结构的图表进行微小更改后&#xff0c;模拟速度更快。 在多个图表和模型中重复使用相同的状态或子表。 易于团队开发&#xff0c;适用于在同一图…

大语言模型在医疗领域的进展、应用和挑战_医疗大语言模型算法csdn

### 概述 本文综述了医学领域大型语言模型&#xff08;LLM&#xff09;的进展、应用和面临的挑战。大型语言模型如ChatGPT在理解和生成人类语言方面显示出了显著的能力&#xff0c;引起了广泛关注。在医学领域&#xff0c;研究人员正致力于利用LLM支持各种医疗任务&#xff0c…

文华财经盘立方博易大师主图指标公式大全源码均线

文华财经盘立方博易大师主图指标公式大全源码均线&#xff1a; N:3; EMA25:EMA(C,25),COLORRED,LINETHICK2; EMA70:EMA(C,70),COLORGREEN,LINETHICK2; EMA450:EMA(C,450),COLORYELLOW,LINETHICK2; CONDA1:EMA25>EMA70&&C>HV(H,6)&&C>EMA450&…

C语言 | Leetcode C语言题解之第179题最大数

题目&#xff1a; 题解&#xff1a; long cmp(int *x, int *y) {unsigned long sx 10, sy 10;while (sx < *x) {sx * 10;}while (sy < *y) {sy * 10;}return sx * (*y) (*x) - sy * (*x) - (*y); }char *largestNumber(int *nums, int numsSize) {qsort(nums, numsSi…

Linux C 程序 【01】最小程序

1.开发背景 基于 RK3568 平台的基础上&#xff0c;编译一个在系统上运行的最小程序。 2.开发需求 由于 RK3568 作为宿主机&#xff0c;在上面编译程序比较慢&#xff0c;所以还是采用在 Ubuntu 下交叉编译后再拷贝到宿主机上运行。 设计实验&#xff1a; 1&#xff09;搭建 M…

数据分析必备:一步步教你如何用matplotlib做数据可视化(14)

1、Matplotlib 图像 Matplotlib包中的图像模块提供加载&#xff0c;重新缩放和显示图像所需的功能。Pillow库支持加载图像数据。Matplotlib仅支持PNG图像。如果本机读取失败&#xff0c;下面显示的命令将回退到Pillow。 此示例中使用的图像是PNG文件&#xff0c;但请记住数据的…

AFLNet入门教学——测试RTSP协议实现Live555(Ubuntu)

1、简介 本文旨在使用AFLNet对RTSP协议实现Live555进行模糊测试。实验环境为&#xff1a;Ubuntu22.04.4AFLNet安装参考&#xff1a;AFLNet入门教学——安装&#xff08;Ubuntu22.04.4&#xff09;-CSDN博客 2、安装Live555 本次实验采取的是live555在2018年8月28日上传的版本…

数据库怎么同步

数据库要怎么同步呢&#xff0c;有很多方法&#xff0c;看你用什么数据库&#xff0c;如果是Sqlserver,你要数据库同步&#xff0c;那么可以使用自带的订阅发布&#xff0c;订阅发布应该是不错的方法&#xff0c;但是我上次要配置双向同步&#xff0c;它的对等发布好像没部署成…

【LeetCode】四、栈相关:有效的括号 + 下一个更大的元素

文章目录 1、栈结构2、Java中的栈3、leetcode20&#xff1a;有效的括号4、leetcode496&#xff1a;下一个更大元素 1、栈结构 和队列相反&#xff0c;栈先进后出 时间复杂度&#xff1a;访问、插入、删除都在栈顶进行操作&#xff0c;时间复杂度为O(1)&#xff0c;搜索需要遍…