首页 > 编程语言 >【Java教程】Day20-21 设计模式:行为型模式——策略模式

【Java教程】Day20-21 设计模式:行为型模式——策略模式

时间:2025-01-07 19:02:29浏览次数:3  
标签:total Java 策略 折扣 模式 算法 设计模式 BigDecimal

1. 引言

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,将它们封装起来,并使得它们可以相互替换。策略模式的主要目的是使得算法可以独立于使用它的客户而变化。它常用于需要根据不同条件选择不同算法的场景。

在Java的标准库中,策略模式得到了广泛的应用,特别是在排序等常见操作中。通过策略模式,我们可以在运行时动态选择算法,而不需要修改原有代码。

2. 策略模式的结构

策略模式包含以下几个核心部分:

  1. 策略接口(Strategy):定义一组算法或行为的接口。

  2. 具体策略类(ConcreteStrategy):实现策略接口,封装具体的算法。

  3. 上下文类(Context):持有一个策略对象,并提供方法来切换策略,供客户端使用。

2.1 策略接口

策略接口定义了算法的公共方法,供具体策略类实现:

javapublic interface DiscountStrategy {    // 计算折扣额度:    BigDecimal getDiscount(BigDecimal total);}

 

2.2 具体策略类

不同的策略实现该接口,根据不同的规则进行计算。我们可以实现多个策略,例如普通用户折扣、满减折扣等。

javapublic class UserDiscountStrategy implements DiscountStrategy {    public BigDecimal getDiscount(BigDecimal total) {        // 普通会员打九折:        return total.multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.DOWN);    }}

 

javapublic class OverDiscountStrategy implements DiscountStrategy {    public BigDecimal getDiscount(BigDecimal total) {        // 满100减20优惠:        return total.compareTo(BigDecimal.valueOf(100)) >= 0 ? BigDecimal.valueOf(20) : BigDecimal.ZERO;    }}
 

 

2.3 上下文类

上下文类持有一个策略对象,并允许在运行时根据需求切换策略:

javapublic class DiscountContext {    // 默认使用普通会员折扣    private DiscountStrategy strategy = new UserDiscountStrategy();    // 允许客户端设置新策略:    public void setStrategy(DiscountStrategy strategy) {        this.strategy = strategy;    }    // 计算价格方法    public BigDecimal calculatePrice(BigDecimal total) {        return total.subtract(this.strategy.getDiscount(total)).setScale(2);    }}

 

2.4 使用示例

使用策略模式的核心优势是可以灵活地切换策略。以下是一个完整的示例,展示了如何根据不同的折扣策略计算购物车总价。

javapublic class Main {    public static void main(String[] args) {        DiscountContext ctx = new DiscountContext();        // 默认使用普通会员折扣        BigDecimal pay1 = ctx.calculatePrice(BigDecimal.valueOf(105));        System.out.println("普通会员折扣: " + pay1);        // 使用满减折扣        ctx.setStrategy(new OverDiscountStrategy());        BigDecimal pay2 = ctx.calculatePrice(BigDecimal.valueOf(105));        System.out.println("满减折扣: " + pay2);        // 使用Prime会员折扣        ctx.setStrategy(new PrimeDiscountStrategy());        BigDecimal pay3 = ctx.calculatePrice(BigDecimal.valueOf(105));        System.out.println("Prime会员折扣: " + pay3);    }}

 

2.5 输出示例

text普通会员折扣: 94.50满减折扣: 85.00Prime会员折扣: 80.00

 

3. 策略模式的应用场景

策略模式非常适用于以下几种场景:

  • 需要多种算法的场景:如果有多个算法可以执行同样的任务(例如排序、折扣计算等),策略模式可以将这些算法封装起来,并在运行时进行选择。

  • 算法或行为变化频繁:当系统中算法或行为会频繁变化时,使用策略模式可以避免修改现有代码,只需添加新的策略类即可。

  • 避免大量的if-else判断:当不同条件下执行不同的行为时,策略模式可以避免复杂的条件判断,增强代码的可维护性。

4. Java标准库中的策略模式应用

策略模式在Java的标准库中有很多应用,最典型的就是Arrays.sort()方法的实现。我们来看一个例子,如何使用策略模式实现忽略大小写的排序。

javaimport java.util.Arrays;public class Main {    public static void main(String[] args) {        String[] array = { "apple", "Pear", "Banana", "orange" };        Arrays.sort(array, String::compareToIgnoreCase); // 使用忽略大小写的排序策略        System.out.println(Arrays.toString(array));    }}

 

这里,Arrays.sort()方法接收一个Comparator对象,它就是一种策略。在排序时,可以传入不同的比较策略,例如按字典顺序排序,按字符串长度排序等。

javaArrays.sort(array, (s1, s2) -> -s1.compareTo(s2));  // 使用倒序排序策略

 

5. 策略模式的优缺点

5.1 优点

  1. 增强了灵活性:策略模式允许在运行时动态选择不同的策略算法,这使得系统更加灵活。

  2. 符合开闭原则:通过扩展策略类来增加新功能,不需要修改现有的代码。

  3. 简化代码:避免了大量的if-elseswitch语句,使代码更加简洁和可维护。

5.2 缺点

  1. 增加了类的数量:每一种策略都需要定义一个具体的策略类,当策略多时,会增加类的数量。

  2. 客户端需要知道所有的策略:客户端需要知道有哪些策略,并负责选择使用哪个策略。

6. 小结

策略模式的核心思想是将算法封装在独立的策略类中,使得算法可以在运行时被动态切换。通过策略模式,我们能够实现不同策略之间的灵活切换,避免了冗长的if-elseswitch语句,使得代码更加简洁和易于维护。策略模式在实际项目中有广泛的应用,特别是在需要根据不同条件选择不同算法或行为时,非常有效。

通过扩展策略,可以轻松地增加新的行为,而不需要修改现有的代码,符合开闭原则,使得系统更具扩展性。

7. 练习

假设网站对于Prime会员的折扣规则是:在满100减20的基础上,再对Prime会员进行七折优惠。请实现这一新策略,并将其与其他策略结合使用。

 

 

 

标签:total,Java,策略,折扣,模式,算法,设计模式,BigDecimal
From: https://blog.csdn.net/max202011161630/article/details/144856974

相关文章

  • @Slf4j 是java里的什么作用
    @Slf4j 是Lombok库提供的一个注解,用于自动生成一个名为 log 的 Logger 实例。Lombok是一个Java库,旨在通过注解减少样板代码(boilerplatecode),使得Java代码更加简洁和易读。主要作用简化日志记录:使用 @Slf4j 注解后,你不需要手动创建 Logger 实例,Lombok会自......
  • java 纤程简介
    在Java中,“纤程”(Fiber)是一种轻量级线程的实现,用于提高多线程计算的效率。纤程的设计目的是减少线程的上下文切换开销,并允许在同一线程上并发执行多个任务。尽管Java目前没有直接支持纤程的标准实现,但随着ProjectLoom的推进,Java正在向支持纤程的方向发展。1.Project......
  • 企业级Java 实体对象类定义规范
    1.查询参数类(Query)命名规则:xxxQuery.java用途:用于封装查询操作的请求参数,通常包含分页、过滤、排序等字段。与数据库查询或API请求紧密相关。示例:ProductQuery.java、UserQuery.java使用场景:查询条件的封装,发送查询请求时使用。2.返回参数类(VO)命名规则......
  • Java Spring Boot实现基于URL + IP访问频率限制
    点击下载《JavaSpringBoot实现基于URL+IP访问频率限制(源代码)》1.引言在现代Web应用中,接口被恶意刷新或暴力请求是一种常见的攻击手段。为了保护系统资源,防止服务器过载或服务不可用,需要对接口的访问频率进行限制。本文将介绍如何使用SpringBoot实现基于URL......
  • Java 异常机制详解:类型、原理、关键字与最佳实践
    异常是Java程序开发中必须掌握的一部分。正确地处理异常不仅可以提高代码的健壮性,还能让程序更易维护。本篇文章将详细讲解Java异常的体系结构、常见类型、关键字的使用及最佳实践,帮助你全面掌握Java异常处理。......
  • JAVA实现抖音、快手短视频解析去除水印下载无水印视频
    前言之间抖音接口有些变动,导致抖音解析代码失效,现在更新下文章的代码,亲测有效。需要引入的pom文件   <!--hutool工具类-->      <dependency>         <groupId>cn.hutool</groupId>         <artifactId>hutool-all</artifactId......
  • Java基础学习(二)
    Java基础知识(二):基础语法本文为个人学习记录,内容学习自狂神说Java注释单行注释(Linecomment)//这是单行注释多行注释(Blockcomment)/*这是多行注释*/文档注释(JavaDoc)/***@DescriptionHelloWorld*@Authorvictoria*/注意:文档注释不同于多行注释,其中......
  • Java基础学习(一)
    Java基础学习(一):入门知识本文为个人学习记录,内容学习自狂神说JavaJava三大版本JavaSE:标准版,主要用于桌面程序和控制台程序开发JavaME:微缩版,主要用于嵌入式开发JavaEE:企业版,主要用于Web端和服务器开发Java相关缩写词JDK:JavaDevelopmentKit,Java开发工具JRE:JavaRu......
  • java进行图片压缩
    图片压缩添加依赖<dependency><groupId>com.siashan</groupId><artifactId>toolkit-image</artifactId><version>1.1.9</version></dependency>使用Thumbnails来进行图片压缩publicstaticvoidcompressImage(Stringp......
  • 解决 Spring Boot 启动错误问题:elasticsearch-java 8.17.0 报 elasticsearch-rest-cli
    解决SpringBoot启动错误问题:Thefollowingmethoddidnotexistorg.elasticsearch.client.RequestOptions$Builder.setHttpAsyncResponseConsumerFactory异常分析与解决方案在使用SpringBoot应用时,可能会遇到以下启动错误:***************************APPLICATIONF......