24-Java策略模式 ( Strategy Pattern )

2024-03-13 05:36

本文主要是介绍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 )的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/803788

相关文章

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

springboot将lib和jar分离的操作方法

《springboot将lib和jar分离的操作方法》本文介绍了如何通过优化pom.xml配置来减小SpringBoot项目的jar包大小,主要通过使用spring-boot-maven-plugin... 遇到一个问题,就是每次maven package或者maven install后target中的ja

Java中八大包装类举例详解(通俗易懂)

《Java中八大包装类举例详解(通俗易懂)》:本文主要介绍Java中的包装类,包括它们的作用、特点、用途以及如何进行装箱和拆箱,包装类还提供了许多实用方法,如转换、获取基本类型值、比较和类型检测,... 目录一、包装类(Wrapper Class)1、简要介绍2、包装类特点3、包装类用途二、装箱和拆箱1、装

如何利用Java获取当天的开始和结束时间

《如何利用Java获取当天的开始和结束时间》:本文主要介绍如何使用Java8的LocalDate和LocalDateTime类获取指定日期的开始和结束时间,展示了如何通过这些类进行日期和时间的处... 目录前言1. Java日期时间API概述2. 获取当天的开始和结束时间代码解析运行结果3. 总结前言在J

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J