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