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

24-Java策略模式 ( Strategy Pattern )

Java策略模式

    • 摘要
    • 实现
    • 范例

  • 策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更加灵活,具有更好的维护性和扩展性。

  • 策略模式属于行为型模式

摘要

1. 意图

  • 针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

2. 主要解决

  • 它将对象和行为分开,将行为定义为一个行为接口和具体的行为实现,说白了策略模式就是用来解决多个if判断的情况的。

3. 何时使用

  • 需要在运行时动态地改变对象的行为
  • 有多个算法可选,客户端需要根据不同的需要选择不同的算法
  • 一个类定义了多种行为,并且这些行为在类的方法中以多个条件语句的形式出现。这时候可以将每种条件分支转化为一个独立的策略

4. 如何解决

  • 将这些通用算法抽象出来

5. 关键代码

  • 策略接口、具体策略类和环境类

6. 应用实例

  • 做一批相机,分配中心需要根据相机的类型去找到不同的工人做相机
  • 电商购物的优惠计算

7. 优点

  • 松耦合:策略模式将不同的策略封装在独立的类中,与上下文对象解耦,增加了代码的灵活性和可维护性。
  • 易于扩展:可以通过添加新的策略类来扩展系统的功能,无需修改现有代码。
  • 符合开闭原则:对于新的策略,无需修改上下文对象,只需要实现新的策略接口即可。

8. 缺点

  • 类数量增多:每个具体策略都需要一个独立的类,如果策略较多,将导致类的数量增加。
  • 上层必须知道所有策略类:上层模块必须知道有哪些策略,并选择合适的策略进行使用,这与迪米特法则是相违背的,我只是想使用了一个策略,我凭什么就要了解这个策略呢?那要你的封装类还有什么 意义?这是原装策略模式的一个缺点。

9. 使用场景

  • 有多个相似的类,只有行为有差异的情况下,可以考虑使用策略模式.
  • 需要在运行时动态切换算法的情况下,可以使用策略模式.
  • 一个系统需要在不同时间应用不同的业务规则情况下,可以使用策略模式
  • 在一个系统中,有许多类需要根据某种规则进行排序,查找等操作的情况下,可以使用策略模式.

10. 注意事项

  • 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题,否则日后的系统维护就会成为一个烫手山芋。

实现

在这里插入图片描述

Java策略模式通常包括以下三种角色:

  • Context(上下文):是策略模式中的核心类,用来管理具体策略实现类的创建,配置和执行,以及在运行时动态地选择具体的策略实现类.
  • Strategy(策略):是一个接口或抽象类,定义了策略实现类的通用方法和属性,具体策略实现类必须实现这些方法和属性.
  • ConcreteStrategy(具体策略):是策略接口的实现类,根据具体业务需求实现了策略接口定义的方法和属性.可以又多个具体策略实现类,Context类在运行时根据需要动态地选择具体的策略实现类.

范例

1. 支付策略接口(Strategy)

Strategy.java

package com.demo.gof;
public interface PaymentStrategy {/*** 支付** @param amount*/void pay(double amount);
}

2. 微信支付和支付宝支付策略类(ConcreteStrategy)

WechatPayment.java

package com.demo.gof;
public class WechatPayment implements PaymentStrategy {private String username;private String password;public WechatPayment(String username, String password) {this.username = username;this.password = password;}/*** 支付** @param amount*/@Overridepublic void pay(double amount) {System.out.println("微信支付:" + amount + "元");}
}

AliPayment.java

package com.demo.gof;
public class AliPayment implements PaymentStrategy{private String username;private String password;public AliPayment(String username, String password) {this.username = username;this.password = password;}/*** 支付** @param amount*/@Overridepublic void pay(double amount) {System.out.println("支付宝支付:" + amount + "元");}
}

3. 购物车类(Context)

ShoppingCart.java

package com.demo.gof;
public class ShoppingCart {private List<Item> itemList;private PaymentStrategy paymentStrategy;public ShoppingCart() {itemList = new ArrayList<>();}public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void addItem(Item item){itemList.add(item);}public void removeItem(Item item){itemList.remove(item);}public double calculateTotal(){return itemList.stream().mapToDouble(Item::getPrice).sum();}public void pay(){paymentStrategy.pay(calculateTotal());}
}

4. 商品类

Item.java

package com.demo.gof;
@Data
public class Item {private String name;private double price;public Item(String name, double price) {this.name = name;this.price = price;}
}

5. 运行执行策略模式

Demo.java

package com.demo.gof;
public class Demo {public static void main(String[] args) {ShoppingCart shoppingCart = new ShoppingCart();Item item1 = new Item("item1",10);Item item2 = new Item("item2",10);shoppingCart.addItem(item1);shoppingCart.addItem(item2);shoppingCart.setPaymentStrategy(new AliPayment("aliPayUsername","aliPayPassword"));shoppingCart.pay();shoppingCart.setPaymentStrategy(new WechatPayment("wechatUsername","wechatPassword"));shoppingCart.pay();}
}

编译运行以上 Java 范例,输出结果如下

在这里插入图片描述

相关文章:

24-Java策略模式 ( Strategy Pattern )

Java策略模式 摘要实现范例 策略模式的重心不是如何实现算法&#xff0c;而是如何组织、调用这些算法&#xff0c;从而让程序结构更加灵活&#xff0c;具有更好的维护性和扩展性。 策略模式属于行为型模式 摘要 1. 意图 针对一组算法&#xff0c;将每一个算法封装到具有共…...

突破编程_C++_C++11新特性(模板的改进与细节)

1 模板右尖括号的改进 在 C11 之前&#xff0c;模板的解析和实例化过程中&#xff0c;右尖括号 > 的处理有时会导致一些意外的结果&#xff0c;特别是在嵌套模板或模板模板参数中。这是因为 C 编译器通常会试图“查看前方”来确定何时结束模板参数的列表&#xff0c;这有时…...

云原生消息流系统 Apache RocketMQ 在腾讯云的大规模生产实践

导语 随着云计算技术的日益成熟&#xff0c;云原生应用已逐渐成为企业数字化转型的核心驱动力。在这一大背景下&#xff0c;高效、稳定、可扩展的消息流系统显得尤为重要。腾讯云高级开发工程师李伟先生&#xff0c;凭借其深厚的技术功底和丰富的实战经验&#xff0c;为我们带…...

Node.js的事件驱动模型(非阻塞I/O)

Node.js的事件驱动模型是它能高效处理并发的关键。这个模型允许Node.js在单个线程上运行&#xff0c;同时通过非阻塞I/O操作来处理成千上万的并发连接。下面是对Node.js事件驱动模型的详细解释&#xff1a; 事件循环&#xff08;Event Loop&#xff09; 事件循环是Node.js事件…...

java过滤器Filter相关知识点汇总

1.Filter概述 Servlet Filter又称Servlet过滤器&#xff0c;它是在Servlet2.3规范中定义的&#xff0c;能够对Servlet容器传给Web资源的request对象和response对象执行检查和修改。 Filter不是Servlet&#xff0c;不能直接访问&#xff0c;其本身也不能生成request对象和resp…...

旅游景区公共广播 园区广播 公路服务区广播

旅游景区公共广播 园区广播 公路服务区广播 旅游景区公共广播 旅游景区公共广播(又称背景音乐)简称BGM&#xff0c;它的主要作用是掩盖噪声并创造一种轻松和谐的气氛&#xff0c;是一种创造轻松愉快环境气氛的音乐。掩盖环境噪声&#xff0c;创造与旅游景区相适应的气氛&#…...

Elastic Stack--09--ElasticsearchRestTemplate

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 spring-data-elasticsearch提供的APIQueryBuildersElasticsearchRestTemplate 方法ElasticsearchRestTemplate ---操作索引 ElasticsearchRestTemplate ---文档操作…...

论坛管理系统|基于Spring Boot+ Mysql+Java+B/S架构的论坛管理系统设计与实现(可运行源码+数据库+设计文档+部署说明+视频演示)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 目录 前台功能效果图 管理员功能登录前台功能效果图 用户功能模块 系统功能设计 数据库E-R图设计 l…...

2022 Task 2 Max Sum of 2 integers sharing first and last digits

Task 2 There is an array A consisting of N integers. What’s the maximum sum of two integers from A that share their first and last digits? For example, 1007 and 167 share their first(1) and last(7) digits, whereas 2002 and 55 do not. Write a function: …...

【分布式websocket】聊天系统消息加密如何做

前言 先介绍一下对称加密算法&#xff0c;在介绍一下加密流程&#xff0c;然后是介绍一下查询加密消息的策略。然后结合现有技术架构然后去选型。 决定采用客户端解密。简而言之就是采用对称服务端加密。然后将加密内容存储到消息表的content字段。然后客户拉取content字段 然…...

网络建设与运维培训介绍和能力介绍

1.开过的发票 3.培训获奖的证书 4合同签署 5.实训设备...

3 种方法限制 K8s Pod 磁盘容量使用

容器在运行期间会产生临时文件、日志。如果没有任何配额机制&#xff0c;则某些容器可能很快将磁盘写满&#xff0c;影响宿主机内核和所有应用。 容器的临时存储&#xff0c;例如 emptyDir&#xff0c;位于目录/var/lib/kubelet/pods 下&#xff1a; /var/lib/kubelet/pods/ …...

05-ESP32-S3-IDF USART

ESP32-S3 IDF USART详解 USART简介 USART是一种串行通信协议&#xff0c;广泛应用于微控制器和计算机之间的通信。USART支持异步和同步模式&#xff0c;因此它可以在没有时钟信号的情况下&#xff08;异步模式&#xff09;或有时钟信号的情况下&#xff08;同步模式&#xff…...

安塔利斯升级php8

1、includes/classes/class.Database.php 255行 multi_query方法加返回类型 :bool query方法加返回类型&#xff1a;: mysqli_result|bool 2、includes/classes/class.Session.php on line 91 Optional parameter $planetID declared before required parameter $dpath is…...

Clickhouse MergeTree 原理(一)

作者&#xff1a;俊达 MergeTree是Clickhouse里最核心的存储引擎。Clickhouse里有一系列以MergeTree为基础的引擎&#xff08;见下图&#xff09;&#xff0c;理解了基础MergeTree&#xff0c;就能理解整个系列的MergeTree引擎的核心原理。 本文对MergeTree的基本原理进行介绍…...

【C语言】字符串函数上

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《C语言》 &#x1f389;道阻且长&#xff0c;行则将至 前言 这篇博客是字符串函数上篇&#xff0c;主要是关于长度不受限制的字符串函数&#xff08;strlen,strcpy,strcat,strcm…...

Java集合基础知识总结(绝对经典)

List接口继承了Collection接口&#xff0c;定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理&#xff0c;还添加了面向位置的操作。 实际上有两种list&#xff1a;一种是基本的ArrayList&#xff0c;其优点在于随机访问元素&#xff0c;另一种是更强大的L…...

Linux:导出环境变量命令export

相关阅读 Linuxhttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm1001.2014.3001.5482 Linux中的内建命令export命令用于创建一个环境变量&#xff0c;或将一个普通变量导出为环境变量&#xff0c;并且在这个过程中&#xff0c;可以给该环境变量赋值。 下面…...

案例--某站视频爬取

众所周知&#xff0c;某站的视频是&#xff1a; 由视频和音频分开的。 所以我们进行获取&#xff0c;需要分别获得它的音频和视频数据&#xff0c;然后进行音视频合并。 这么多年了&#xff0c;某站还是老样子&#xff0c;只要加个防盗链就能绕过。&#xff08;防止403&#xf…...

清华把大模型用于城市规划,回龙观和大红门地区成研究对象

引言&#xff1a;参与式城市规划的新篇章 随着城市化的不断推进&#xff0c;传统的城市规划方法面临着越来越多的挑战。这些方法往往需要大量的时间和人力&#xff0c;且严重依赖于经验丰富的城市规划师。为了应对这些挑战&#xff0c;参与式城市规划应运而生&#xff0c;它强…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...