首页 > 编程语言 >行为设计模式 -观察者模式- JAVA

行为设计模式 -观察者模式- JAVA

时间:2024-10-23 22:17:28浏览次数:3  
标签:JAVA dispenseChain 处理 dispense 观察者 amount 设计模式 public DispenseChain

责任链设计模式

前言
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。

作者:神的孩子都在歌唱

一 .简介

百度百科:责任链模式是一种行为设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织分配责任。

个人理解: 通过责任链方式可以找到能够处理客户端请求的对象。感觉就跟Switch 或者try-catch 一样,当前不匹配就继续往下匹配。

责任链模式涉及到的角色如下所示:

● **抽象处理者(Handler)角色:**定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。

● **具体处理者(ConcreteHandler)角色:**具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

二. 案例

网上看了很多案例,感觉ATM取款机这个案例最容易理解。需求是让用户输入一个金额数(amount),然后ATM机会将输入的金额数从大到小(能够分配的纸币类型是100元 20 元 10元)进行分配。如果用户输入的金额不是10的倍数,就抛出错误。

image-20240604171326864

其实这个实现起来很简单,不过为了将每种类型的纸币进行解耦,所以需要使用责任链方式去解决

2.1 抽象处理者(Handler)角色

定义分配的处理链接口

/**
 * @author chenyunzhi
 * @date 2024/6/4 16:27
 * @Description 分配的处理链接口
 */
public interface DispenseChain {

    /**
     * 要执行的下一个链(对象)
     */
    void setNextChain(DispenseChain nextChain);


    /**
     * 执行分配的方法
     */
    void dispense(Integer amount);
}

2.2 具体处理者(ConcreteHandler)角色

定义每种纸币的对象

Yuan100Dispenser

/**
 * @author chenyunzhi
 * @date 2024/6/4 16:30
 * @Description
 */
public class Yuan100Dispenser implements DispenseChain{

    private DispenseChain dispenseChain;
    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.dispenseChain = nextChain;
    }

    @Override
    public void dispense(Integer amount) {
        if (amount >= 100) {
            int num = amount / 100;
            int remainder = amount % 100;
            System.out.println("分配了" + num + "张100元");
            // 进入下一个分配
            if (remainder != 0) {
                this.dispenseChain.dispense(remainder);
            }
        } else {
            this.dispenseChain.dispense(amount);
        }
    }
}

Yuan20Dispenser

/**
 * @author chenyunzhi
 * @date 2024/6/4 16:30
 * @Description
 */
public class Yuan20Dispenser implements DispenseChain{

    private DispenseChain dispenseChain;
    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.dispenseChain = nextChain;
    }

    @Override
    public void dispense(Integer amount) {
        if (amount >= 20) {
            int num = amount / 20;
            int remainder = amount % 20;
            System.out.println("分配了" + num + "张20元");
            // 进入下一个分配
            if (remainder != 0) {
                this.dispenseChain.dispense(remainder);
            }
        } else {
            this.dispenseChain.dispense(amount);
        }
    }
}

Yuan10Dispenser

/**
 * @author chenyunzhi
 * @date 2024/6/4 16:30
 * @Description
 */
public class Yuan10Dispenser implements DispenseChain{

    private DispenseChain dispenseChain;
    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.dispenseChain = nextChain;
    }

    @Override
    public void dispense(Integer amount) {
        if (amount >= 10) {
            int num = amount / 10;
            int remainder = amount % 10;
            System.out.println("分配了" + num + "张10元");
            // 进入下一个分配
            if (remainder != 0) {
                this.dispenseChain.dispense(remainder);
            }
        } else {
            this.dispenseChain.dispense(amount);
        }
    }
}

2.3 测试

这一步我们将三种纸币连接起来,创建链进行测试

/**
 * @author chenyunzhi
 * @date 2024/6/4 16:48
 * @Description 测试
 */
public class ChainOfResponsibilityPatternTest {


    private DispenseChain chain;
    /**
     * 初始化atm分配链
     */
    public  ChainOfResponsibilityPatternTest() {
        this.chain = new Yuan100Dispenser();
        Yuan20Dispenser yuan20Dispenser = new Yuan20Dispenser();
        Yuan10Dispenser yuan10Dispenser = new Yuan10Dispenser();

        chain.setNextChain(yuan20Dispenser);
        yuan20Dispenser.setNextChain(yuan10Dispenser);
    }
    public static void main(String[] args) {
        ChainOfResponsibilityPatternTest patternTest = new ChainOfResponsibilityPatternTest();
        for (int i=0; i<3; i++){
            System.out.println("----------输入领取金额-----------");
            Scanner scanner = new Scanner(System.in);
            int amount = scanner.nextInt();
            if (amount % 10 != 0) {
                System.out.println("需要输入10的倍数的金额");
                continue;
            }
            patternTest.chain.dispense(amount);
            System.out.println("----------分配结束-----------");
        }

    }
   
}

image-20240604171106716

通过上面的组装链,就能够将atm的需求实现了。

三. 结论

3.1 优缺点

1,优点:

  • 降低了对象之间的耦合度: 该模式降低了请求发送者和接收者的耦合度。

  • 增强了系统的可扩展性:可以根据需要增加新的请求处理类,满足开闭原则。

  • 增强了给对象指派职责的灵活性:当工作流程发生变化,可以动态地改变链内的成员或者修改它们的次序,也可动态地新增或者删除责任。

  • 责任链简化了对象之间的连接:一个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。

  • 责任分担:每个类只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

2,缺点:

  • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  • 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

3.2 示例

  • java.util.logging.Logger#log()
  • javax.servlet.Filter#doFilter()

3.3 要点

  1. 责任链设计模式可以很好地实现失去耦合,但如果大多数代码在所有实现中都是通用的,那么它会带来大量实现类和维护问题的权衡。
  2. 客户端不知道链的哪一部分将处理请求,它会将请求发送到链中的第一个对象

作者:神的孩子都在歌唱

本人博客:https://blog.csdn.net/weixin_46654114

转载说明:务必注明来源,附带本人博客连接。

标签:JAVA,dispenseChain,处理,dispense,观察者,amount,设计模式,public,DispenseChain
From: https://blog.csdn.net/weixin_46654114/article/details/143194938

相关文章

  • Java 解析 XML 转换为 Json
    我们使用Java开发项目时偶尔会需要使用到Xml文件的解析,一般情况下都会使用DOM4j、SAX、JDOM等方案,但这些方案比较代码编写较为繁琐。我们经常使用的Json进行数据传输或存储,如果能够将Xml快速转换为Json,将会大大减轻我们后续开发和维护的工作量。本篇博客简单介绍使用......
  • springboot+vue展位设计模型库网站的java开发与设计
    目录系统实现截图详细技术介绍本课题软硬件环境核心代码部分展示其他springboot项目推荐详细视频演示源码获取系统实现截图详细技术介绍系统采用了基于SpringBoot、Vue和MySQL的三层结构体系。前端部分通过Vue框架构建用户界面,实现页面展示和交互功能,后端则利......
  • JAVA开源项目 基于Vue和SpringBoot购物商城网站
    本文项目编号T032,文末自助获取源码\color{red}{T032,文末自助获取源码}......
  • JAVA开源项目 基于Vue和SpringBoot高校心理教育辅导系统
    本文项目编号T031,文末自助获取源码\color{red}{T031,文末自助获取源码}......
  • Java Spring的常用注解详解和案例示范
    1.Spring常用注解概述1.1@Component@Component是Spring的基础注解之一,它用于将类标记为Spring容器中的一个组件。通过@Component注解,Spring会自动将该类注册为一个Bean,供依赖注入使用。使用示例:@ComponentpublicclassUserService{publicvoidperf......
  • Java程序启动“Hello, World!”详细分析
    在Java编程世界中,“Hello,World!”程序是学习旅程的起点。这个程序虽然简单,但它展示了Java程序的基本结构和从编写到运行的全过程。下面,我们将详细分析如何启动一个Java程序并输出“Hello,World!”。一.编写Java源代码首先,我们需要编写一个包含main方法的Java类。main......
  • vue3+java基于Spring Boot的爱老助老服务平台源码 lw 部署
    目录功能介绍具体实现截图技术介绍开发核心技术介绍:技术创新点vue3和vue2的区别:核心代码部分展示非功能需求分析系统开发流程软件测试源码获取功能介绍爱老助老服务平台的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使......
  • javascript对象介绍
    1.什么是对象?在JavaScript中,对象是一个无序的键值对集合,可以用来存储数据和功能。对象可以包含原始值、函数(方法)以及其他对象,是构建复杂数据结构和实现面向对象编程的基础。2.创建对象2.1字面量方式最常见的创建对象的方法是使用对象字面量:constperson={n......
  • java基础2024(5.集合)
    集合(Collection)是一组用于存储和操作对象的数据结构。Java集合框架(JavaCollectionsFramework,JCF)提供了一个统一的架构,用于表示和操作集合,它包含了一系列接口、实现类以及算法。Collection接口Collection接口是集合框架的根接口,它扩展了Iterable接口,定义了所有集合类型共......
  • javascript数组splice和slice介绍
    一splice1.概述splice是JavaScript数组对象的一个方法,用于改变原数组的内容。它可以添加、删除或替换数组中的元素。2.语法array.splice(start,deleteCount,item1,item2,...)start:需要改变的数组的起始索引。如果是负数,则表示从数组末尾开始计数。de......