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

news2024/10/7 6:47:02

 我是荔园微风,作为一名在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深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。
 


 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring boot Websocket(使用笔记)

使用websocket有两种方式&#xff1a;1是使用sockjs&#xff0c;2是使用h5的标准。使用Html5标准自然更方便简单&#xff0c;所以记录的是配合h5的使用方法。 1、pom 核心是ServerEndpoint这个注解。这个注解是Javaee标准里的注解&#xff0c;tomcat7以上已经对其进行了实现&a…

学内核之十八:纸上得来终觉浅,绝知此事要躬行

目录 0 前言 1 ioremap、vmalloc与原子上下文 2 copy_to_user与进程上下文 3 fasync与指针初始化 4 wait_event_interruptible与条件变量 0 前言 大家都知道&#xff0c;内核开发跟应用开发&#xff0c;体验是完全不同的&#xff0c;尤其是驱动。一方面要掌握扎实的语言基…

MySQL 基本轮廓

目录 什么是数据库 主流数据库 基本使用 连接服务器 服务器管理 使用案例 创建数据库 使用数据库 创建数据库表 表中插入数据 查询表中的数据 服务器&#xff0c;数据库&#xff0c;表关系 MySQL架构 什么是数据库 存储数据用文件就可以了&#xff0c;为什么还要弄…

每日一问-ChapGPT-20230409-中医基础-四诊之望诊

文章目录每日一问-ChapGPT系列起因每日一问-ChapGPT-20230409-中医基础-四诊之望诊中医中的望闻问切介绍&#xff0c;以及对应的名家望诊的具体细节望诊拓展当日总结每日一问-ChapGPT系列起因 近来看了新闻&#xff0c;看了各种媒体&#xff0c;抖音&#xff0c;官媒&#xff…

【数据库原理 • 四】数据库设计和规范化理论

前言 数据库技术是计算机科学技术中发展最快&#xff0c;应用最广的技术之一&#xff0c;它是专门研究如何科学的组织和存储数据&#xff0c;如何高效地获取和处理数据的技术。它已成为各行各业存储数据、管理信息、共享资源和决策支持的最先进&#xff0c;最常用的技术。 当前…

jvm调优一:从源码级别了解jvm类加载机制

目录 一、类加载运行全过程 类加载器加载类的过程 二、类加载器和双亲委派机制 类加载器类型 类加载器初始化过程 双亲委派机制 为什么要设计双亲委派机制&#xff1f; 全盘负责委托机制 一、类加载运行全过程 当我们用java命令运行某个类的main函数启动程序时&#xff0c…

Kube-proxy 使用 iptables 模式时,通过 Service 服务发布入口如何到达 Pod ?

写在前面 被问到这个问题&#xff0c;整理相关的笔记当 kube-proxy 模式设置为 iptables 的时候&#xff0c;通过 SVC 服务发布入口如何到达 Pod&#xff1f;博文内容涉及&#xff1a; 问题简单介绍三种常用的服务发布方式到Pod报文路径解析 当前集群为版本为v1.25.1Demo 演示使…

linux内核结构以及内核模块编程

1、linux内核结构 1.1、单内核与微内核结构 1.1.1、什么是单内核结构和微内核结构 linux操作系统是一个单内核的结构&#xff0c;它的各个子系统之间可以直接调用 比如说文件系统、内存管理、进程管理以及网络系统和进程间通信它们互相之间可以直接调用只有一些核心的代码它…

记录npm的安装过程

一、访问官网&#xff08;https://nodejs.org/en&#xff09;&#xff0c;下载nodejs并安装&#xff1a; 然后一路点击next直到安装完成&#xff0c;环境变量已经自动添加好了&#xff1a; 通过设置环境变量&#xff0c;改变本地仓库地址&#xff1a; 可以看到&#xff0c;…

一条更新语句的执行流程又是怎样的呢?

当一个表上有更新的时候&#xff0c;跟这个表有关的查询缓存会失效&#xff0c;所以这条语句就会把表T上所有缓存结果都清空。这也就是我们一般不建议使用查询缓存的原因。 接下来&#xff0c;分析器会通过词法和语法解析知道这是一条更新语句。优化器决定要使用ID这个索引。然…

LNMP网站框架搭建(yum方式安装)

1. nginx 的yum安装 1.1 搭建nginx相关的yum源 注意&#xff1a;本次安装所获得的软件包都是来源于httpd源&#xff08;都是由该软件包厂商提供&#xff09;。所以切记不能像往常一样直接使用本地源去安装一切包 vim /etc/yum.repos.d/nginx.repo [nginx-stable] namenginx…

Linux--tty

Linux 终端(TTY) TTY 是 Teletype 或 Teletypewriter 的缩写&#xff0c;原来是指电传打字机&#xff0c;后来这种设备逐渐键盘和显示器取代。不管是电传打字机还是键盘显示器&#xff0c;都是作为计算机的终端设备存在的&#xff0c;所以 TTY 也泛指计算机的终端(terminal)设…

【CSS】更改用户界面样式 ① ( 更改鼠标样式 | 更改鼠标样式应用场景 | 代码示例 )

文章目录一、更改鼠标样式二、更改鼠标样式代码示例三、更改鼠标样式应用场景一、更改鼠标样式 为对象元素设置 cursor 样式 , 可以更改鼠标移动到该元素上的显示样式 ; cursor 样式常用属性值 : default : 默认鼠标样式 , 白色箭头鼠标 ;pointer : 小手形状 ;move : 移动 - …

C++——初始化列表 | explicit关键字 | static成员

文章目录&#x1f490;专栏导读&#x1f490;文章导读&#x1f337;初始化列表&#x1f33a;初始化列表的形式&#x1f33a;初始化列表的注意事项&#x1f337;explicit关键字&#x1f33a;单参数构造函数&#x1f33a;多参数构造函数&#x1f337;static成员&#x1f33a;stat…

SprigBoot学习笔记(五)

监控 监控的意义 可视化监控平台 监控原理 自定义监控指标 监控的意义 监控服务状态是否宕机 监控服务运行指标(内存、虚拟机、线程、请求等) 监控日志 管理服务(服务下线) 监控的实施方式 显示监控信息的服务器:用于获取服务信息,并显示对应的信息 运行的服务:启动时主动…

Node【五】内置模块 【http模块】

文章目录&#x1f31f;前言&#x1f31f;http模块&#x1f31f; 1.引入http模块&#x1f31f; 2.创建服务&#x1f31f; 3.添加头信息&#x1f31f; 4.搭建一个简单的服务器&#xff1a;&#x1f31f; 5.Request对象&#x1f31f; 6.Response对象&#x1f31f; 7.练习&#xff…

【力扣周赛】第340场周赛

【力扣周赛】第340场周赛6361&#xff1a;对角线上的质数题目描述解题思路6360&#xff1a;等值距离和题目描述解题思路6361&#xff1a;对角线上的质数 题目描述 描述&#xff1a;给你一个下标从 0 开始的二维整数数组 nums &#xff0c;返回位于 nums 至少一条 对角线 上的…

webgl-原生纹理贴图

踩坑&#xff1a; 1、图片不显示&#xff1a;图片分辨率为非2的幂次方&#xff0c;图片不能被渲染。图形变成黑方块 2的N次幂&#xff1a;1 2 4 8 16 32 64 128 256 512 1024 2048 4096…… 2、几何图形配置映射方式&#xff0c;顶点坐标和纹理坐标对应需要注意&#xff0c;构…

并行分布式计算 并行计算机体系结构

文章目录并行分布式计算 并行计算机体系结构并行计算机结构模型SIMD 单指令多数据流PVP 并行向量处理机SMP 对称多处理机MPP 大规模并行处理机DSM 分布式共享存储多处理机COW 工作站集群总结并行计算机访存模型UMA 均匀存储访问模型NUMA 非均匀存储访问模型COMA 全高速缓存存储…

OpenCV实战之广角相机拍照算法

拍照是手机中的一项重要功能&#xff0c;目前常见的千元机中都包含数个相机模组&#xff0c;能够实现虚化拍照、美颜、广角拍照、夜景等功能。手机是一个拥有巨大销量的电子产品&#xff0c;因此成为图像处理算法的一个重要落地场景。很多AI公司聚焦于此&#xff0c;如虹软、旷…