Windows环境下实现设计模式——职责链模式(JAVA版)

 我是荔园微风,作为一名在IT界整整25年的老兵,今天总结一下Windows环境下如何编程实现职责链模式(设计模式)。

不知道大家有没有这样的感觉,看了一大堆编程和设计模式的书,却还是很难理解设计模式,无从下手。为什么?因为你看的都是理论书籍。

我今天就在Windows操作系统上安装好JAVA的IDE编程工具,并用JAVA语言来实现一个职责链模式,真实的实现一个,你看懂代码后,自然就明白了。

职责链模式Chain of Responsibility Pattern  (行为型设计模式)

定义:避免将一个请求的发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

上面定义听懂了吗?莫名其妙看不懂对吧。所以我们还是来看看实现生活中的例子。

职责链模式可以说是行为型设计模式里最简单的一种了,学这个模式根本是无压力的,所以大家千万不要紧张。在很多情况下可以处理某个请求的对象并不止一个,例如你要把你写的新闻稿交给领导审批,那你先应该给科长审,科长审完处长审,处长审完局长审,局长审完秘书长审,秘书长审完主席审。在这个过程中你送审的新闻稿可以看成是一个请求对象,而不同级别的审批者都可以处理该请求对象,除了科长之外,你不需要与其他审批者交互,只需要等待结果即可。在审批过程中如果某一个审批者认为不符合条件,则请求中止,否则就把新闻稿递交给下一个审批者,最后由主席来确定你这个新闻稿能否发出去。
 

如上,科长、处长、局长、秘书长、主席都可以处理新闻稿,他们构成一个处理新闻稿的链式结构,新闻稿沿着这条链进行传递,这条链就称为职责链。


职责链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并让请求沿着链传递,由链上的处理者对请求进行相应的处理,客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,将请求的发送者和请求的处理者解耦。

对于JAVA程序员来说,那真是好,大家在进行java web编程时,经常会遇到一个概念叫过滤器,过滤器其实用的就是职责链的设计思想。比如在处理程序时,加入了三个过滤器,并按一定顺序放好,如果我觉得顺序不对,我可以调换过滤器的位置,我也可以拿掉其中一个过滤器,或者增加第四个过滤器,第四个过滤器可以放在任意位置,体现出职责链很好的适用性。这就是这种设计模式的思想。

 职责链模式结构的核心在于引入了一个抽象处理者。  在职责链模式结构图中包含如下几个角色:

 Handler(抽象处理者):它定义了一个处理请求的接口,一般设计为抽象类,由于不同的具体处理者处理请求的方式不同,因此在其中定义了抽象请求处理方法。因为每一个处理者的下家还是一个处理者,因此在抽象处理者中定义了一个抽象处理者类型的对象(如结构图中的successor),作为其对下家的引用。通过该引用,处理者可以连成一条链。

ConcreteHandler(具体处理者):它是抽象处理者的子类,可以处理用户请求,在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者;在具体处理者中可以访问链中下一个对象,以便请求的转发。

在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下重新组织链。 模式的核心在于抽象处理者类的设计,抽象处理者的典型代码如下所示:

public abstract class Handler {
	
    //维持这个链的延续
    protected Handler successor;
	
	public void setSuccessor(Handler successor) {
		this.successor=successor;
	}
	
	public abstract void handleRequest(String request);
}

抽象处理者类定义了对下家的引用对象,以便将请求转发给下家,该对象的访问符可设为protected,在其子类中可以使用。在抽象处理者类中声明了抽象的请求处理方法,具体实现交由子类完成。具体处理者是抽象处理者的子类,它能处理请求,不同的具体处理者以不同的形式实现抽象请求处理方法handleRequest(),还能转发请求,如果该请求超出了当前处理者类的权限,可以将该请求转发给下家。具体处理者类的典型代码如下:
 


public class ConcreteHandler extends Handler {
	public void handleRequest(String request) {
		if (请求满足条件) {
			//处理请求
		}
		else {
			this.successor.handleRequest(request);  //转发请求
		}
	}
}

在具体处理类中通过对请求进行判断可以做出相应的处理。一般是在使用该职责链的客户端中创建职责链。职责链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求。 

  
  Handler handler1, handler2, handler3;
  handler1 = new ConcreteHandlerA();
  handler2= new ConcreteHandlerB();
  handler3= new ConcreteHandlerC();
  //创建职责链
  handlerl.setSuccessor(handler2);
  handler2.setSuccesgor(handler3):
  //发送请求,请求对象通常为自定义类型
  bandler1.handleRequest("请求对象");

应用实例
  

某事业单位使用上面要求的事采云系统。该事业单位的采购审批是分级进行的,即根据采购金额的不同由不同层次的领导审批,副主任可以审批5万元以下(不包括5万元)的采购单,主任可以审批5万元至10万元(不包括10万元)的采购单,秘书长可以审批10万元至50万元(不包括50万元)的采购单,集体讨论可以决定50万元及以上的采购单,这样的事采云系统可以使用职责链模式设计并实现该系统。

(1)PurchaseRequest:采购单类,充当请求类。

package designpatterns.cor;

public class PurchaseRequest {
    private double amount;  //采购金额
    private int number;  //采购单编号
    private String purpose;  //采购目的
    
    public PurchaseRequest(double amount, int number, String purpose) {
        this.amount = amount;
        this.number = number;
        this.purpose = purpose;
    }
    
    public void setAmount(double amount) {
        this.amount = amount;
    }
    
    public double getAmount() {
        return this.amount;
    }
    
    public void setNumber(int number) {
        this.number = number;
    }
    
    public int getNumber() {
        return this.number;
    }
    
    public void setPurpose(String purpose) {
        this.purpose = purpose;
    }
    
    public String getPurpose() {
        return this.purpose;
    }
}

(2)Leader:审批领导类,是抽象处理者 

package designpatterns.cor;

public abstract class Leader {
    protected Leader successor; //定义后继对象
    protected String name; //审批者姓名
    
    public Leader(String name) {
        this.name = name;
    }
 
    //设置后继者
    public void setSuccessor(Leader successor) { 
        this.successor = successor;
    }
 
    //抽象请求处理方法
    public abstract void processRequest(PurchaseRequest request);
}

(3)副主任类:具体处理者

package designpatterns.cor;

public class DeputyDirector extends Leader {
    public DeputyDirector(String name) {
        super(name);
    }
    
    //具体请求处理方法
     public void processRequest(PurchaseRequest request) {
         if (request.getAmount() < 50000) {
             System.out.println("副主任" + this.name + "审批采购单:" + request.getNumber() + ",金额:" + request.getAmount() + "元,采购到的货物:" + request.getPurpose() + "。");  //处理请求
         }
         else {
             this.successor.processRequest(request);  //转发请求
         }    
     }
}

(4)主任类:具体处理者

package designpatterns.cor;

public class Director extends Leader {
    public Director(String name) {
        super(name);
    }
    
    //具体请求处理方法
     public void processRequest(PurchaseRequest request) {
         if (request.getAmount() < 100000) {
             System.out.println("主任" + this.name + "审批采购单:" + request.getNumber() + ",金额:" + request.getAmount() + "元,采购到的货物:" + request.getPurpose() + "。");  //处理请求
         }
         else {
             this.successor.processRequest(request);  //转发请求
         }    
     }
}

(5)秘书长类:具体处理者

package designpatterns.cor;

public class SecretaryGeneral extends Leader {
    public SecretaryGeneral(String name) {
        super(name);
    }
    
    //具体请求处理方法
     public void processRequest(PurchaseRequest request) {
         if (request.getAmount() < 500000) {
             System.out.println("秘书长" + this.name + "审批采购单:" + request.getNumber() + ",金额:" + request.getAmount() + "元,采购到的货物:" + request.getPurpose() + "。");  //处理请求
         }
         else {
             this.successor.processRequest(request);  //转发请求
         }
     }
}

(6)集体讨论类:具体处理者

package designpatterns.cor;

public class Congress extends Leader {
    public Congress(String name) {
        super(name);
    }
    
    //具体请求处理方法
     public void processRequest(PurchaseRequest request) {
         System.out.println("集体讨论采购事宜:" + request.getNumber() + ",金额:" + request.getAmount() + "元,采购到的货物:" + request.getPurpose() + "。");        //处理请求
     }    
}

(7)Client:客户端测试类

package designpatterns.cor;

public class Client {
	public static void main(String[] args) {
		Leader a,b,c,d;
		a = new DeputyDirector("职工1");
		b = new Director("职工2");
		c = new SecretaryGeneral("职工3");
		d = new Congress("所有职工");
	
		//创建职责链
		a.setSuccessor(b);
		b.setSuccessor(c);
		c.setSuccessor(d);
		
		//创建采购单
		PurchaseRequest pr1 = new PurchaseRequest(40000,10001,"采购高级工作站");
		a.processRequest(pr1);
		
		PurchaseRequest pr2 = new PurchaseRequest(80000,10002,"采购复印机");
		a.processRequest(pr2);
	
		PurchaseRequest pr3 = new PurchaseRequest(180000,10003,"采购服务器");
		a.processRequest(pr3);
 
		PurchaseRequest pr4 = new PurchaseRequest(900000,10004,"采购大型存储阵列");
		a.processRequest(pr4);
	}
} 

如果职责链仅仅就是上面所说的这些那完全没有意义,我们来看看这种设计模式的真正意义何在,我们往下看。

 如果需要在系统增加一个新的具体处理者,如增加一个经理(Manager)角色可以审批5万元至8万元(不包括8万元)的采购单,需要编写一个新的具体处理者类Manager,作为抽象处理者类Leader的子类,实现在Leader类中定义的抽象处理方法,如果采购金额大于等于8万元,则将请求转发给下家,只需要增加代码就行了,而不需要去改变原来的代码。是不是很不错??

由于链的创建过程由客户端负责,因此增加新的具体处理者类对原有类库无任何影响,无须修改已有类的源代码,符合“开闭原则”。在客户端代码中,如果要将新的具体请求处理者应用在系统中,需要创建新的具体处理者对象,然后将该对象加入职责链中。

各位小伙伴,这次我们就说到这里,下次我们再深入研究windows环境下的各类设计模式实现。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。
 


 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Maven的进阶操作

系列文章目录 Maven进阶操作的学习 文章目录系列文章目录前言一、分模块开发与设计二、依赖管理1.依赖传递2.可选依赖3.排除依赖三、继承与聚合1.聚合2.继承四、属性1.属性2.版本管理五、多环境配置与应用1.多环境开发2.跳过测试六、私服1.私服简介2.私服仓库分类3.资源上传与…

比GPT-4 Office还炸裂,阿里版GPT全家桶来袭

目录 【新智元导读】 文案、策划、邮件&#xff0c;一键搞定 不用写代码&#xff0c;草稿秒变小程序 聊天记录不用翻&#xff0c;摘要自动生成 会上开小差&#xff1f;不怕&#xff0c;AI替你记了 AI版十万个为什么&#xff0c;有问必答 剁手买买买&#xff0c;连手都不…

Excel技能之数据验证,总有一款适合你

用户填写的内容&#xff0c;是未知的&#xff0c;不可靠的。但是&#xff0c;我们要对数据的规范、格式、条件做出限制&#xff0c;既能保证数据的质量&#xff0c;也能统一每个人的行为。最大限度去避免垃圾数据的录入&#xff0c;眼不见心不烦&#xff0c;让心情美美的。 数…

Python之数据库操作(连接数据库,增删改查操作,易错点理解)

文章目录 前言一、Python之数据库操作二、pymysql 安装三、pymysql 包引入 连接数据库创建游标执行sql数据 - 增删改查要获取查询结果数据关闭游标&#xff0c;关闭数据库连接总结前言 记录&#xff1a;Python操作数据库的步骤&#xff0c;不容易理解的地方。 一、Python之数据…

C++模板基础(九)

完美转发与 lambda 表达式模板 void f(int& input) {std::cout << "void f(int& input)\t" << input << \n; }void f(int&& input) {std::cout << "void f(int&& input)\t" << input << \n;…

uniapp - 全平台兼容的 “多图上传“ 功能,搭配 uview 组件库中的 upload 上传组件(附带详细的示例源码及注释,可直接复制使用或简单修改)

效果图 使用 uniapp 开发,多平台全端兼容的多图上传功能,支持限制个数及移除等。 组件库使用的是 uview 框架,上传组件基于 Upload组件,功能完美无bug。 准备阶段 Upload组件支持手动上传与

Docker安装Elasticsearch详细步骤

1 安装elasticsearch 1.1 拉取镜像 docker pull elasticsearch:7.12.11.2 创建挂载目录 mkdir -p /app/elasticsearch/confecho "http.host: 0.0.0.0" >> /app/elasticsearch/conf/elasticsearch.ymlmkdir -p /app/elasticsearch/datamkdir -p /app/elastic…

GaussDB工作级开发者认证—第三章开发设计建议

一. 数据库对象命名和设计建议 二. 表设计最佳实践 三. SQL查询最佳实践 SQL 最佳实践 - SELECT 避免对大字段执行order by&#xff0c;group by等引起排序的操作避免频繁使用count()获取大表行数慎用通配符字段 “*”避免在select目标列中使用子查询统计表中所有记录数时&…

Leetcode刷题之环形链表

莫等闲&#xff0c;白了少年头&#xff0c;空悲切。 --岳飞 目录 1.环形链表 2.环形链表Ⅱ 1.环形链表 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next …

想制作出专业水准的音视频?掌握H.264编码技巧是关键

H.264编码原理 H.264&#xff0c;也被称为先进视频编码&#xff08;AVC&#xff09;&#xff0c;是目前最流行的视频编码标准之一&#xff0c;其压缩效率很高。H.264编码基于视频编码的原始数据&#xff0c;使用一系列算法和技术以更小的比特率呈现更高质量的视频。以下是H.26…

SpringBoot整合xxl-job详细教程

SrpingBoot整合xxl-job&#xff0c;实现任务调度说明调度中心执行器调试整合SpringBoot说明 Xxl-Job是一个轻量级分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。Xxl-Job有…

主机发现和端口扫描基本原理和工具选择

发现主机 扫描端口指令sudo nmap -sn ip 实则是封装ping指令 可以找目标靶机 sudo nmap --min-rate 10000 -p- 192.168.10.191 -p端口号 -p-从一开始扫 设置最小速度扫描 -p-指定靶机 10000是较好的速度 在工作中最好扫两遍 UDP扫描 sudo nmap -sU --min-rate 10000 …

Golang每日一练(leetDay0035) 二叉树专题(4)

目录 103. 二叉树的锯齿形层序遍历 Binary Tree Zigzag Level Order Traversal &#x1f31f;&#x1f31f; 104. 二叉树的最大深度 Maximum Depth of Binary-tree] &#x1f31f; 105. 从前序与中序遍历序列构造二叉树 Construct-binary-tree-from-preorder-and-inorder-…

一文弄懂访问者模式

关于设计模式&#xff0c;我们得结合生活中的案例来学习&#xff1b;最近我在网上也看了不少文章&#xff0c;今天想跟大家分享一下关于访问者模式的一些知识&#xff0c;先来看一个简单的案例吧。 相信大家都去过医院&#xff0c;看完病&#xff0c;医生都会给我们开一个处方…

2023最新面试题-Java-6

1. Date API Java 8 在包java.time下包含了一组全新的时间日期API。新的日期API和开源的Joda-Time库差不多&#xff0c;但 又不完全一样&#xff0c;下面的例子展示了这组新API里最重要的一些部分&#xff1a; Clock类提供了访问当前日期和时间的方法&#xff0c;Clock是时区敏…

环境变量概念详解!(4千字长文)

环境变量&#xff01; 文章目录环境变量&#xff01;环境变量PATHexportexport的错误用法定义命令行变量环境变量哪里来的其他各种环境变量HOMEHOSTNAMELOGNAMEHISTSIZEPWD环境变量相关指令echoenvgetenv——相关函数&#xff01;exportsetunset命令行参数argcargvenvpenvironp…

自动化面试题4

1、工业中常见的通信方式都有哪些&#xff0c;各自特点是什么&#xff1f; 2、对于一台新的伺服驱动器来说&#xff0c;需要设置哪几个方面的参数&#xff1f; &#xff08;1&#xff09;参数初始化 &#xff08;2&#xff09;点动测试电机旋转方向 &#xff08;3&#xff09;惯…

Android创建项目

目录 创建Android项目 配置项目结构 创建安卓模拟器 模拟器运行 HelloWorld 应用 真机运行 HelloWorld 应用 创建Android项目 打开 Android studio 工具&#xff0c;选择Project&#xff0c;选择 New Project 由于现在是教程博客&#xff0c;所以我们随便选择 一个 空 Ac…

Java使用elasticjob实现定时任务(v2.1.5)

elastic是一个定时任务库 https://shardingsphere.apache.org/elasticjob/index_zh.html 项目结构 ​依赖 <dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-core</artifactId><version>2.1.5</version>&…

5.Java循环控制语句

Java循环控制语句 循环是Java中应用最为广泛的一个知识点&#xff0c;所以也是很需要掌握的。所谓循环&#xff0c;即通过判断条件&#xff0c;重复执行一段代码&#xff0c;根据条件的变化&#xff0c;来确定代码是否执行&#xff0c;执行次数。 一、循环结构 1、while循环…