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

【精选】设计模式——策略设计模式-两种举例说明,具体代码实现

Java策略设计模式

在这里插入图片描述

简介

策略设计模式是一种行为型设计模式,它允许在运行时选择算法的行为。

在软件开发中,我们常常需要根据不同情况采取不同的行为。通常的做法是使用大量的条件语句来实现这种灵活性,但这会导致代码变得复杂、难以维护和扩展。

策略设计模式通过将每种行为封装到一个独立的类中,并使它们可以相互替换,从而避免了大量的条件判断语句。

在这里插入图片描述

示例

假设我们正在开发一个电商平台,需要计算订单的折扣金额。根据不同的用户类型,有不同的折扣策略。

首先,我们定义一个抽象策略类DiscountStrategy,它包含一个抽象方法calculateDiscount用于计算折扣金额。

public abstract class DiscountStrategy {public abstract double calculateDiscount(double price);
}

然后,我们创建具体的策略类:RegularCustomerDiscount(普通用户折扣策略)和VIPCustomerDiscount(VIP用户折扣策略)。它们分别继承自DiscountStrategy并实现了calculateDiscount方法。

public class RegularCustomerDiscount extends DiscountStrategy {@Overridepublic double calculateDiscount(double price) {// 普通用户折扣计算逻辑return price * 0.9;}
}public class VIPCustomerDiscount extends DiscountStrategy {@Overridepublic double calculateDiscount(double price) {// VIP用户折扣计算逻辑return price * 0.8;}
}

最后,我们创建一个上下文类Order,它包含一个策略对象,并提供一个方法calculateFinalPrice用于计算订单的最终价格。

public class Order {private DiscountStrategy discountStrategy;public void setDiscountStrategy(DiscountStrategy discountStrategy) {this.discountStrategy = discountStrategy;}public double calculateFinalPrice(double price) {return discountStrategy.calculateDiscount(price);}
}

现在,我们可以使用策略模式来计算不同用户类型的订单折扣金额,而无需修改订单类的代码。

public class Main {public static void main(String[] args) {Order order = new Order();// 普通用户订单DiscountStrategy regularCustomerDiscount = new RegularCustomerDiscount();order.setDiscountStrategy(regularCustomerDiscount);double regularCustomerPrice = order.calculateFinalPrice(100);System.out.println("普通用户价格:" + regularCustomerPrice);// VIP用户订单DiscountStrategy vipCustomerDiscount = new VIPCustomerDiscount();order.setDiscountStrategy(vipCustomerDiscount);double vipCustomerPrice = order.calculateFinalPrice(100);System.out.println("VIP用户价格:" + vipCustomerPrice);}
}

输出结果:

普通用户价格:90.0
VIP用户价格:80.0

例子二:
让我们以一个商场销售促销活动的场景为例进行代码实现。

假设在商场中有多种促销活动,如打折、满减和赠品活动。根据顾客的购买情况和优惠条件,商场需要动态选择不同的促销策略来给顾客提供最优惠的价格。

首先,我们定义一个抽象的促销策略接口 PromotionStrategy

public interface PromotionStrategy {double applyDiscount(double price);
}

然后,我们创建具体的促销策略类,分别实现打折、满减和赠品活动的算法:

public class DiscountPromotion implements PromotionStrategy {private double discountRate;public DiscountPromotion(double discountRate) {this.discountRate = discountRate;}@Overridepublic double applyDiscount(double price) {return price * (1 - discountRate);}
}public class FullReductionPromotion implements PromotionStrategy {private double fullAmount;private double reductionAmount;public FullReductionPromotion(double fullAmount, double reductionAmount) {this.fullAmount = fullAmount;this.reductionAmount = reductionAmount;}@Overridepublic double applyDiscount(double price) {if (price >= fullAmount) {return price - reductionAmount;} else {return price;}}
}public class FreeGiftPromotion implements PromotionStrategy {private String gift;public FreeGiftPromotion(String gift) {this.gift = gift;}@Overridepublic double applyDiscount(double price) {System.out.println("You got a free gift: " + gift);return price;}
}

接下来,我们定义一个商场类 ShoppingMall,其中包含一个促销策略的成员变量,并提供一个设置促销策略的方法:

public class ShoppingMall {private PromotionStrategy promotionStrategy;public void setPromotionStrategy(PromotionStrategy promotionStrategy) {this.promotionStrategy = promotionStrategy;}public double calculatePrice(double price) {if (promotionStrategy != null) {price = promotionStrategy.applyDiscount(price);}return price;}
}

现在我们可以使用这些类进行测试:

public class Main {public static void main(String[] args) {ShoppingMall shoppingMall = new ShoppingMall();// 设置打折促销策略PromotionStrategy discountPromotion = new DiscountPromotion(0.2);shoppingMall.setPromotionStrategy(discountPromotion);double discountedPrice = shoppingMall.calculatePrice(100);System.out.println("Discounted price: " + discountedPrice);// 设置满减促销策略PromotionStrategy fullReductionPromotion = new FullReductionPromotion(200, 50);shoppingMall.setPromotionStrategy(fullReductionPromotion);double reducedPrice = shoppingMall.calculatePrice(300);System.out.println("Reduced price: " + reducedPrice);// 设置赠品促销策略PromotionStrategy freeGiftPromotion = new FreeGiftPromotion("T-shirt");shoppingMall.setPromotionStrategy(freeGiftPromotion);double giftPrice = shoppingMall.calculatePrice(100);System.out.println("Final price: " + giftPrice);}
}

这段代码首先创建了一个商场对象 shoppingMall,然后通过设置不同的促销策略来计算价格。在不同的促销策略下,商场会根据顾客购买的物品和优惠条件动态选择最优惠的价格。

希望这个例子能够帮助你更好地理解策略模式的实际应用!如果你还有其他问题,请随时提问。
通过使用策略设计模式,我们可以轻松地添加新的折扣策略,而无需修改订单类的代码。这样使得代码更加灵活、可扩展和易于维护。

策略模式的优势

在这里插入图片描述

策略设计模式有以下几个优势:

  1. 灵活性:策略模式可以根据需要在运行时选择不同的算法,而不需要修改原有的代码。这使得系统更加灵活,可以根据不同的需求动态地切换和替换算法。

  2. 可扩展性:由于每个算法都被封装到独立的策略类中,因此很容易添加新的策略。只需要创建一个新的策略类并实现相应的算法即可,而不会影响其他代码的稳定性。

  3. 代码复用:策略模式可以将通用的算法逻辑封装到一个抽象策略类中,然后通过继承和实现来扩展具体的策略类。这样可以避免重复编写相同的代码,提高了代码的复用性。

  4. 单一责任原则:策略模式能够将不同的算法逻辑分离开来,使得每个策略类只负责自己的算法实现。这符合单一责任原则,使得代码更加清晰、可读性更强。

策略模式的应用场景

策略设计模式在许多场景中都可以发挥作用。以下是一些常见的应用场景:

  1. 排序算法:不同的排序算法有不同的实现方式,如冒泡排序、快速排序、插入排序等。使用策略模式可以将这些算法封装到独立的策略类中,并在运行时选择合适的算法。

  2. 支付方式:在线购物平台通常支持多种支付方式,如信用卡支付、支付宝、微信支付等。使用策略模式可以将每种支付方式封装到一个独立的策略类中,并根据用户的选择来动态切换支付方式。

  3. 日志记录:不同类型的日志可能需要采用不同的记录方式,如文件记录、数据库记录、网络发送等。使用策略模式可以将不同的记录方式封装到策略类中,根据配置或条件来选择合适的记录方式。

  4. 缓存策略:在开发中,我们经常会使用缓存来提高系统的性能。不同的数据访问模式可能需要采用不同的缓存策略,如先进先出(FIFO)、最近最少使用(LRU)等。通过使用策略模式,我们可以将不同的缓存策略封装到独立的策略类中,并在运行时选择合适的策略。

  5. 图像处理:图像处理涉及许多算法,如调整图像大小、滤镜效果、图像旋转等。使用策略模式可以将不同的图像处理算法封装到独立的策略类中,并根据用户需求选择合适的算法来处理图像。

这些只是策略设计模式的一些常见应用场景,实际上它可以应用于各种需要根据不同条件选择不同行为的情况。通过使用策略模式,我们可以使代码更加灵活、可维护和可扩展,同时降低了代码的复杂度。

希望本文对你理解和应用策略设计模式有所帮助!如果你还有任何问题,请随时提问。

策略模式与其他设计模式的区别

策略模式与其他设计模式有一些相似之处,但也有一些明显的区别。

  1. 策略模式 vs. 工厂模式

    • 工厂模式是一种创建型模式,它将对象的创建逻辑封装到一个工厂类中,客户端通过工厂类来创建对象。而策略模式是一种行为型模式,它将不同的算法封装到独立的策略类中,并在运行时选择合适的策略。
    • 工厂模式主要关注对象的创建,而策略模式主要关注算法的选择和切换。
    • 工厂模式通常用于创建具有相同接口的对象,而策略模式可以用于封装任意类型的算法。
  2. 策略模式 vs. 模板方法模式

    • 模板方法模式是一种行为型模式,它定义了一个算法的骨架,将一些步骤延迟到子类实现。而策略模式则将整个算法封装到独立的策略类中,并在运行时动态选择策略。
    • 模板方法模式强调保持算法骨架的稳定性,而策略模式强调算法的灵活性。
  3. 策略模式 vs. 委托模式

    • 委托模式是一种对象组合模式,它将任务的执行委托给其他对象来完成。而策略模式则是将不同的算法封装到独立的策略类中,并在运行时选择合适的策略。
    • 委托模式侧重于任务的分配和执行,而策略模式侧重于算法的选择和切换。

总的来说,策略模式通过将不同的算法封装到独立的策略类中,使得代码更加灵活、可扩展和可维护。它与工厂模式、模板方法模式和委托模式有一些相似之处,但也有明显的区别。根据具体的需求和场景,我们可以选择适合的设计模式来解决问题。

总结

策略设计模式是一种非常常用且有价值的设计模式,它可以提供灵活、可扩展和可复用的代码结构。通过封装不同的算法到独立的策略类中,策略模式能够简化代码、降低耦合性,并使得系统更加可维护和可扩展。

在实际开发中,我们经常会遇到需要根据不同条件选择不同行为的情况,这时候策略模式就是一个很好的选择。希望本文对你理解和应用策略设计模式有所帮助!

如果你想深入了解策略设计模式,可以参考《Head First 设计模式》一书中关于策略模式的章节,它详细介绍了策略设计模式的原理和实现方式。

相关文章:

【精选】设计模式——策略设计模式-两种举例说明,具体代码实现

Java策略设计模式 简介 策略设计模式是一种行为型设计模式,它允许在运行时选择算法的行为。 在软件开发中,我们常常需要根据不同情况采取不同的行为。通常的做法是使用大量的条件语句来实现这种灵活性,但这会导致代码变得复杂、难以维护和扩…...

外包干了3个月,技术倒退2年。。。

先说情况,大专毕业,18年通过校招进入湖南某软件公司,干了接近6年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…...

微信小程序:chooseimage从本地相册选择图片或使用相机拍照

文档 https://uniapp.dcloud.net.cn/api/media/image.html#chooseimage https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html 代码示例 const res await uni.chooseImage({count: 1, //默认9sizeType: [original, compressed], //可以…...

「Swift」取消UITableView起始位置在状态栏下方开始

前言:在写页面UI时发现,当隐藏了NavigationBar时,即使UITableView是从(0,0)进行布局,也会一直在手机状态栏下方进行展示布局,而我的想法是希望UITableView可以从状态栏处就进行展示布局 当前页面展示: 问题…...

android高版本适配使用Tools.java

随着android版本的提升,原生Tools不公开并且不能被正常使用,为了延续项目的功能,修改如下: /** Copyright (C) 2006 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License&quo…...

面试官:说说webpack中常见的Loader?解决了什么问题?

面试官:说说webpack中常见的Loader?解决了什么问题? 一、是什么 loader 用于对模块的"源代码"进行转换,在 import 或"加载"模块时预处理文件 webpack做的事情,仅仅是分析出各种模块的依赖关系&a…...

【蓝桥杯省赛真题50】Scratch智能计价器 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解

目录 scratch智能计价器 一、题目要求 编程实现 二、案例分析 1、角色分析...

折半查找(数据结构实训)

题目: 标准输入输出 题目描述: 实现折半查找。要求查找给定的值在数据表中相应的存储位置。本题目假定输入元素均按非降序输入。 输入: 输入包含若干个测试用例,第一行为测试用例个数k。每个测试用例占3行,其中第一行为…...

AR助推制造业智能转型:实时远程协作与可视化引领生产创新

制造商面临着多方面的变革,技术的兴起催生了工业物联网(IIoT),改变了现代工厂的外貌、系统和流程。同时,全球竞争压力和不断变化的员工队伍要求采用新的员工培训方法,并重新审视工人在工厂中的角色。尽管如…...

【用unity实现100个游戏之18】从零开始制作一个类CSGO/CS2、CF第一人称FPS射击游戏——基础篇3(附项目源码)

文章目录 本节最终效果前言素材人物移动音效枪口火焰和开火音效枪口灯光弹孔和火花添加武器随镜头手臂摇摆效果源码完结 本节最终效果 前言 本节主要实现添加音效,和一些特效、武器摆动调整。 素材 素材,为了方便我直接用了unity免费的音效输出&#…...

sed 流式编辑器

使用方式: 1,前置指令 | sed 选项 定址符指令 2,sed 选项 定址符指令 被处理文档 选项: -n 屏蔽默认输出 -i写入文件 -r支持扩展正则 指令: p输出 d删除 s替换 sed -n 1p user //输出第1行 sed -n…...

Linux shell编程学习笔记33:type 命令

目录 0 引言1 type 命令的功能和格式 1.1 type命令的功能1.2 type 命令的格式2 type命令用法实例 2.1用type命令查看shell内置命令(以echo命令为例)2.2 用type命令查看别名(以ls命令为例)2.3 用type命令同时查看shell内置命令和别…...

【数据结构】—红黑树(C++实现)

🎬慕斯主页:修仙—别有洞天 💜本文前置知识: AVL树 ♈️今日夜电波:Letter Song—ヲタみん 1:36━━━━━━️💟──────── 5:35 …...

内衣洗衣机和手洗哪个干净?高性价比内衣洗衣机推荐

通常来说,我们的内衣裤对卫生要求比较高,毕竟是贴身穿的,所以如果和一般的衣物一起洗,就怕会有细菌互相感染。所以很多用户为了内衣裤的卫生都会选择自己手动洗,但手洗一方面很费时间和人力,另一方面又很伤…...

TikTok与互动广告:品牌如何打破传统界限

随着数字时代的蓬勃发展,广告行业也经历了翻天覆地的变革。在这个变革的浪潮中,TikTok作为一款崭新的社交媒体平台,通过其独特的短视频形式为品牌提供了全新的互动广告机会。 本文将深入探讨TikTok与互动广告的结合,以及品牌如何…...

跟着Nature Communications学习Hisat-Trinity-PASA等分析流程

一边学习,一边总结,一边分享! 详细教程请访问: 组学分析流程 本期分析流程 Hisat2-SamtoolsTrinity_GG_denovoPASA… 本期教程文章 题目:Genomic insights into local adaptation and future climate-induced vulnerability of a keystone forest tree in East Asia H…...

Unity中Batching优化的动态合批

文章目录 前言一、动态合批的规则1、材质相同是合批的前提,但是如果是材质实例的话,则一样无法合批。2、支持不同网格的合批3、动态合批需要网格支持的顶点条件二、我们导入一个模型并且制作一个Shader,来测试动态合批1、我们选择模型的 Mesh…...

2022年第十一届数学建模国际赛小美赛B题序列的遗传过程解题全过程文档及程序

2022年第十一届数学建模国际赛小美赛 B题 序列的遗传过程 原题再现: 序列同源性是指DNA、RNA或蛋白质序列之间的生物同源性,根据生命进化史中的共同祖先定义[1]。DNA、RNA或蛋白质之间的同源性通常根据它们的核苷酸或氨基酸序列相似性来推断。显著的相…...

【Linux】静态库与动态库制作及运行原理

Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法…感兴趣就关注我吧!你定不会失望。 本篇导航 0. 静态库与动态库1. 制作与使用静态库2. 制作与使用动态库3. 动态库是如何被加载到内存?3.1程序地址空间 0. 静态库…...

工具站推荐

自己搭了一个文本工具站 TextTool,包含了常用的文本功能。 我自己比较常用 行转列、列转行、下划线替换的功能。 欢迎各位大佬提意见和建议...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...