策略模式入门:基本概念与应用

目录

  • 策略模式
    • 策略模式结构
    • 策略模式应用场景
    • 策略模式优缺点
    • 练手题目
      • 题目描述
      • 输入描述
      • 输出描述
      • 题解

策略模式

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

策略模式结构

在这里插入图片描述

  1. 上下文(Context)维护指向具体策略的引用,且仅通过策略接口与该对象进行交流。
  2. 策略 (Strategy) 接口是所有具体策略的通用接口, 它声明了一个上下文用于执行策略的方法。
  3. 具体策略 (Concrete Strategies) 实现了上下文所用算法的各种不同变体。
  4. 当上下文需要运行算法时, 它会在其已连接的策略对象上调用执行方法。 上下文不清楚其所涉及的策略类型与算法的执行方式。
  5. 客户端 (Client) 会创建一个特定策略对象并将其传递给上下文。 上下文则会提供一个设置器以便客户端在运行时替换相关联的策略。

通用代码结构示例


//策略接口声明了某个算法各个不同版本间所共有的操作。
interface Strategy{...
}//具体策略会在遵循策略基础接口的情况下实现算法。
class ConcreteStrategies implements Strategy{...
}//抽象生成器类
class Context{//抽象策略private Strategy strategy = null;//抽象策略设置具体策略public Context(Strategy s){this.strategy=s;}//封装具体的方法...}//客户端
public class Client{Stragety stragety = new ConcrateStrategies();Context context = new Context(Strategy);...
}

策略模式应用场景

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

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

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

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

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

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

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

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

在这里插入图片描述

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

策略模式优缺点

优点:

  • 你可以在运行时切换对象内的算法。
  • 你可以将算法的实现和使用算法的代码隔离开来。
  • 你可以使用组合来代替继承。
  • 开闭原则。 你无需对上下文进行修改就能够引入新的策略。

缺点:

  • 如果你的算法极少发生改变,那么没有任何理由引入新的类和接口。使用该模式只会让程序过于复杂。
  • 客户端必须知晓策略间的不同——它需要选择合适的策略。
  • 许多现代编程语言支持函数类型功能, 允许你在一组匿名函数中实现不同版本的算法。 这样, 你使用这些函数的方式就和使用策略对象时完全相同, 无需借助额外的类和接口来保持代码简洁。

练手题目

题目描述

小明家的超市推出了不同的购物优惠策略,你可以根据自己的需求选择不同的优惠方式。其中,有两种主要的优惠策略:

  1. 九折优惠策略:原价的90%。
  2. 满减优惠策略:购物满一定金额时,可以享受相应的减免优惠。

具体的满减规则如下:

满100元减5元

满150元减15元

满200元减25元

满300元减40元

请你设计一个购物优惠系统,用户输入商品的原价和选择的优惠策略编号,系统输出计算后的价格。

输入描述

输入的第一行是一个整数 N(1 ≤ N ≤ 20),表示需要计算优惠的次数。

接下来的 N 行,每行输入两个整数,第一个整数M( 0 < M < 400) 表示商品的价格, 第二个整数表示优惠策略,1表示九折优惠策略,2表示满减优惠策略

输出描述

每行输出一个数字,表示优惠后商品的价格

在这里插入图片描述

题解

1、初次解决思路,简单的策略模式实现。

import java.util.Scanner;interface Strategy {void preferentialMethod(int price);
}class ConcreteStrategy1 implements Strategy {public void preferentialMethod(int price) {double discountedPrice = 0.9 * price;System.out.println((int) discountedPrice);}
}class ConcreteStrategy2 implements Strategy {public void preferentialMethod(int price) {if (price >= 300) {price = price - 40;} else if (price < 300 && price >=200) {price = price - 25;} else if (price < 200 && price >= 150) {price = price - 15;} else if (price <150 && price >= 100) {price = price - 5;}System.out.println(price);}
}class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void executeStrategy(int price) {strategy.preferentialMethod(price);}
}public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);try {int num = scanner.nextInt();scanner.nextLine(); for (int i = 0; i < num; i++) {String input = scanner.nextLine();String[] parts = input.split(" ");if (parts.length != 2) {System.out.println("输入错误!");break;}int price = Integer.parseInt(parts[0]);int type = Integer.parseInt(parts[1]);Context context = null;switch (type) {case 1:context = new Context(new ConcreteStrategy1());break;case 2:context = new Context(new ConcreteStrategy2());break;default:System.out.println("无效选择,请输入1或2");continue;}context.executeStrategy(price);}} catch (Exception e) {System.out.println("An error occurred: " + e.getMessage());} finally {scanner.close();}}
}

2、优化后,使用策略枚举类实现。

import java.util.Scanner;interface Strategy {void preferentialMethod(int price);
}//策略枚举类
enum DiscountStrategy implements Strategy {STRATEGY1 {@Overridepublic void preferentialMethod(int price) {double discountedPrice = 0.9 * price;System.out.println((int) discountedPrice);}},STRATEGY2 {@Overridepublic void preferentialMethod(int price) {int[][] discountRules = {{300, 40},{200, 25},{150, 15},{100, 5}};for (int[] rule : discountRules) {if (price >= rule[0]) {price -= rule[1];break;}}System.out.println(price);}};public static DiscountStrategy fromType(int type) {switch (type) {case 1:return STRATEGY1;case 2:return STRATEGY2;default:throw new IllegalArgumentException("无效选择,请输入1或2");}}
}class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void executeStrategy(int price) {strategy.preferentialMethod(price);}
}public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);try {int num = scanner.nextInt();scanner.nextLine();for (int i = 0; i < num; i++) {try {String input = scanner.nextLine();String[] parts = input.split(" ");if (parts.length != 2) {System.out.println("输入错误!");continue;}int price = Integer.parseInt(parts[0]);int type = Integer.parseInt(parts[1]);DiscountStrategy strategy = DiscountStrategy.fromType(type);Context context = new Context(strategy);context.executeStrategy(price);} catch (NumberFormatException e) {System.out.println("输入格式错误,请输入有效的价格和类型!");} catch (IllegalArgumentException e) {System.out.println(e.getMessage());}}} catch (Exception e) {System.out.println("An error occurred: " + e.getMessage());} finally {scanner.close();}}
}

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

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

相关文章

数字研发·驱动变革 | 2024达索系统装备行业数字化研发专题研讨会成功举办

2024年6月28日&#xff0c;由百世慧举办的“数字研发驱动变革|2024达索系统装备行业数字化研发专题研讨会”在达索系统&#xff08;重庆&#xff09;智能制造创新中心成功举办。 随着全球制造业向着智能化、数字化转型&#xff0c;我国工业装备行业也面临着转型升级的压力和机遇…

Gym cuda error: invalid resource handle

gym模拟的时候&#xff0c; 出现问题&#xff1a; sim和gym的定义如下&#xff1a; from isaacgym import gymapi,gymtorch import math,random# 1. Simulation Setup gym gymapi.acquire_gym()# get default set of parameters sim_params gymapi.SimParams() sim_params.u…

企业多存储方式如何兼顾安全统一管理、便捷流畅访问的双向需求?

数据和文件存储是企业最基础的需求&#xff0c;常见的存储方式有磁盘存储、NAS存储、SAN存储、云存储、分布式存储、闪存存储等&#xff1b;随着企业规模的扩大、业务结构的复杂化&#xff0c;企业内部可能会同时出现多种存储方式、多个存储设备并行使用的情况。 这样的使用场景…

【启明智显技术分享】Model3C芯片电阻屏RTP配置、调试与测试指南

一、背景 本指南将详细介绍启明智显的Model3C芯片电阻屏RTP配置、调试与测试指南。无论您是电子爱好者、开发者还是工程师&#xff0c;这份指南都能助您快速上手并充分利用这款触摸屏的各项功能。 二、芯片介绍 Model3C是一款基于RISC-V的高性能、国产自主、工业级高清显示与…

面试篇-系统设计题总结

这里记录一些有趣的系统设计类的题目&#xff0c;一般大家比较喜欢出的设计类面试题目会和高可用系统相关比如秒杀和抢红包等。欢迎大家在评论中评论自己遇到的题目&#xff0c;本篇文章会持续更新。 1、设计一个抢红包系统 抢红包系统其实也是秒杀类中的一个场景&#xff0…

类的动态加载-双亲委派模型

java反射基础 Java 基础 - 反射机制详解 | Java 全栈知识体系 (pdai.tech) 类的动态加载 参考链接&#xff1a;类的动态加载 构造是和实例化也就是对象相关的。 静态代码块是在初始化的时候就调用的 Class.forName();就会调用静态代码块 forName&#xff0c;加载类时默认…

你们叫AI,我们叫DI

大家好&#xff0c;才是真的好。 最近Notes/Domino产品在做哪些更新&#xff0c;想必大家都很好奇。 从2022年年末到现在&#xff0c;快两年了&#xff0c;任何一个有追求的大企业或巨头&#xff0c;应该都在追求实现一件事情&#xff1a;AI人工智能。 从小道消息来看&#…

【高级篇】分区与分片:MySQL的高级数据管理技术(十三)

引言 在上一章,我们探讨了MySQL的主从复制与高可用性,这是构建健壮数据库架构的基石。现在,让我们深入到更高级的主题——分区与分片,这些技术对于处理大规模数据集和提升数据库性能至关重要。我们将详细介绍表分区的概念、类型及分片技术的应用,为下一章讨论MySQL集群与…

解决Vue3中路由页面跳转出现白屏,刷新页面之后展示正常的问题

遇到这个问题&#xff0c;首先需要检查根组件标签最外层是否包含了个最大的div盒子来包裹内容。如下图所示&#xff1a; 我的项目就是因为没有将两块内容放到一个大盒子里面&#xff0c;所以才会出现白屏的问题。然后我去查了相关的资料&#xff0c;了解到这个问题是Vue组件渲染…

TSINGSEE智能分析网关V4人员区域徘徊AI检测:算法原理介绍及技术应用场景

一、引言 在现代社会&#xff0c;随着科技的不断发展&#xff0c;视频监控系统已广泛应用于各个领域&#xff0c;如公共安全、商业管理、交通监控等。其中&#xff0c;区域徘徊检测算法作为一种重要的视频分析技术&#xff0c;能够有效地识别出特定区域内人员的徘徊行为&#…

Spring Cloud Alibaba - Sentinel 分布式系统流量哨兵

目录 概述特征基本概念 安装Sentinel微服务引入Sentinel案例流控规则&#xff08;流量控制&#xff09;流控模式-直接流控模式-关联流控模式-链路流控效果-快速失败流控效果-预热WarmUp流控效果-排队等候 流控规则&#xff08;并发线程数控制&#xff09;熔断规则&#xff08;熔…

Django 安装 Zinnia 后出现故障

在Django中安装和配置Zinnia时遇到故障可能有多种原因&#xff0c;通常包括版本兼容性、依赖关系或配置问题。这里提供一些常见的解决方法和调试步骤&#xff0c;帮助大家解决问题。 首先&#xff0c;确保您安装的Zinnia版本与Django版本兼容。查看Zinnia的官方文档或GitHub页…

Linux库概念及相关编程(动态库-静态库)

Linux库概念及相关编程 分文件编程案例 分文件编程是指将程序按功能模块划分成不同的文件进行编写&#xff0c;这种方法有以下好处&#xff1a; 功能责任划分&#xff1a;每个文件对应一个功能模块&#xff0c;职责明确&#xff0c;易于理解和维护。方便调试&#xff1a;可以…

C++左值/右值/左值引用/右值引用

1&#xff09;C入门级小知识&#xff0c;分享给将要学习或者正在学习C开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 左值和右值的概念&#xff1a; 早期的c语言中关于左值和右值的定义&a…

每日一题——Python实现PAT乙级1026 程序运行时间(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 代码结构和逻辑 时间复杂度 空间复杂度 代码优化建议 总结 我要更强 …

交换机需要多大 buffer

有点违背直觉&#xff0c;但是真事儿&#xff0c;交换机过境的流越多&#xff0c;所需 buffer 越小&#xff0c;这是为什么&#xff1f; 范氏(范雅各布森&#xff0c;van jacobson)管道的 aimd 流建议 buffer_size 为 bdp&#xff0c;这很容易理解&#xff0c;因为 aimd 流最小…

币界网讯,预计以太坊现货 ETF 将于 7 月中旬推出

刚刚 ETF Store 总裁 Nate Geraci 在 X &#xff08;前Twitter&#xff09;平台上宣布&#xff0c;备受数字货币市场期待的SEC以太坊现货 ETF提案&#xff0c;将于7 月中旬通过美国证券交易委员会&#xff08;SEC&#xff09;批准。Nate Geraci透露修订后的 S-1 文件将于 7 月 …

pnpm的坑

请问pnpm的两个坑怎么解决&#xff1a; 第一个坑&#xff1a;没有节省磁盘空间 我已经配置了依赖的存储位置&#xff0c; 但我在项目里pnpm install以后&#xff0c;发现依赖包还是很大&#xff0c; 然后发现里面的链接并不是指向先前配置的依赖存储位置&#xff0c;而是指…

【数智化人物展】袋鼠云CEO宁海元:大模型时代,Data+AI将成为新的基础设施

宁海元 本文由袋鼠云CEO宁海元投递并参与由数据猿联合上海大数据联盟共同推出的《2024中国数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 身处这个瞬息万变的数字经济时代&#xff0c;传统的生产模式往往依赖于经验和固定的流程&…

k8s-第六节-数据持久化

数据持久化 kubernetes 集群不会为你处理数据的存储&#xff0c;需要为数据库挂载一个磁盘来确保数据的安全。 可以选择云存储、本地磁盘、NFS。 本地磁盘&#xff1a;可以挂载某个节点上的目录&#xff0c;但是这需要限定 pod 在这个节点上运行 云存储&#xff1a;不限定节…