OOP设计模式[JAVA]——03职责链模式
职责链模式 Responsibility of Chain
在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
职责链模式的意图
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。[当然也有可能不被任何对象处理]
职责链模式的结构
参与者
- Handler——定义一个处理请求的接口。如果需要,接口可以定义一个方法,以设定和返回对下家的引用。这个角色通常由一个JAVA抽象类或者JAVA接口实现。其示意性类图如下图所示。图中的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
- ConcreteHandler——处理它所负责的请求。
——可访问它的后继者
——如果可处理该请求,就处理;否则将该请求转发给它的后继者 - Client——向链上的具体处理者对象提交请求
协作
当客户提交一个请求时,请求沿链传递直至有一个ConcreteHandler 对象负责处理它。
使用场景
职责链可能是一条直线、一个环链或者一个树结构的一部分。为了方便,我们使用一个简单的例子。公司人事的请假流程:请假一天组长批了即可、两到三天项目经理批了即可、三天以上需总经理批准。我们来看看源码实现:
//抽象处理角色:
package headfirst.ChainOfResponsibility; /**
* @author Nick Lau
* 抽象处理角色
*/
public abstract class Handler {
//持有处理请求的对象
protected Handler successor = null; //取得后继者
public Handler getSuccessor() {
return successor;
} //设置下一个处理请求的对象
public void setSuccessor(Handler successor) {
this.successor = successor;
} /**
* @param role 角色
* @param days 请假天数
* @return 审批成功或失败后返回的提示
*/
public abstract String handleRequest(String role, int days);
}
下面是具体处理者的示意性源码。显然,处理者的逻辑非常简单,如果一个具体处理者有下家,就将请求传递给下家;如果没有下家,就处理掉。
package headfirst.ChainOfResponsibility; /**
* @author Nick Lau
* TeamLeader处理请假事项
*/
public class TeamLeader extends Handler { @Override
public String handleRequest(String role, int days) {
// TODO Auto-generated method stub
String tips = "";
if (days == 1) {
if ("TeamLeader".equals(role)) {
tips = "TeamLeader agree " + days + " day(s) leave.";
} else {
tips = "请假1天TeamLeader批准即可。";
}
} else {//传递给下一个继承者处理
if (getSuccessor() != null)
return getSuccessor().handleRequest(role, days);
}
return tips;
} }
package headfirst.ChainOfResponsibility;
public class ProjectManager extends Handler {
@Override
public String handleRequest(String role, int days) {
// TODO Auto-generated method stub
String tips = "";
if (days > 1 && days <=3) {
if ("ProjectManager".equals(role)) {
tips = "ProjectManager agree " + days + " day(s) leave.";
} else {
tips = "请假1天TeamLeader批准即可;4天以上需总经理批准!";
}
} else {//如果还有下一个处理者则传递给下一个继承者处理
if (getSuccessor() != null)
return getSuccessor().handleRequest(role, days);
}
return tips;
}
}
package headfirst.ChainOfResponsibility;
public class GeneralManager extends Handler{
@Override
public String handleRequest(String role, int days) {
// TODO Auto-generated method stub
String tips = "";
if (days > 3) {
if ("GeneralManager".equals(role)) {
tips = "GeneralManager agree " + days + " day(s) leave.";
} else {
tips = role + "无权限处理" + days + "天请假事宜。";
}
} else {//传递给下一个继承者处理
if (getSuccessor() != null)
return getSuccessor().handleRequest(role, days);
}
return tips;
}
}
当然,在大多数情况下,这么简单的处理逻辑是没有实际用途的。真实的处理逻辑和所研究的系统商业逻辑密切相关,这里使用最简化的商业逻辑,有助于我们将精力集中到如何将模式应用到设计中去。
客户端的源码清单如下:
package headfirst.ChainOfResponsibility;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Handler teamLeader = new TeamLeader();
Handler projectManager = new ProjectManager();
Handler generalManager = new GeneralManager();
teamLeader.setSuccessor(projectManager);
projectManager.setSuccessor(generalManager);
String test1 = teamLeader.handleRequest("TeamLeader", 1);
System.out.println(test1);
String test2 = teamLeader.handleRequest("ProjectManager", 1);
System.out.println(test2);
System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n");
String test3 = teamLeader.handleRequest("ProjectManager", 3);
System.out.println(test3);
String test4 = teamLeader.handleRequest("GeneralManager", 3);
System.out.println(test4);
System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n");
String test5 = teamLeader.handleRequest("ProjectManager", 11);
System.out.println(test5);
String test6 = teamLeader.handleRequest("GeneralManager", 11);
System.out.println(test6);
System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n");
}
}
客户端输出如下:
TeamLeader agree 1 day(s) leave.
请假1天TeamLeader批准即可。
+++++++++++++++++++++++++++++++++++++++++++++++++
ProjectManager agree 3 day(s) leave.
请假1天TeamLeader批准即可;4天以上需总经理批准!
+++++++++++++++++++++++++++++++++++++++++++++++++
ProjectManager无权限处理11天请假事宜。
GeneralManager agree 11 day(s) leave.
+++++++++++++++++++++++++++++++++++++++++++++++++
效果
职责链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求。一个链可以是一条线、一棵树、也可以是一个环。链的拓扑结构可以是单连通的或多连通的,职责链模式并不指定职责链的拓扑结构。但是职责链模式要求在同一个时间里,命令只可以被传给一个下家(或被处理掉)而不能传给多个下家。
下面情况可以使用职责链模式:
- 系统已经有一个由处理者对象组成的链。这个链可能由合成模式给出。
- 有多于一个的处理者对象会处理一个请求,而事先并不知道到底由哪一个处理者对象处理该请求。这个处理者对象是动态确定的。
- 系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象。
- 处理一个请求的处理者对象集合需要动态地被指定。
OOP设计模式[JAVA]——03职责链模式的更多相关文章
- Java设计模式之《职责链模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6530089.html 职责链模式(称责任链模式)将请求的处理对象像一条长链一般组合起来,形 ...
- 设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型)
设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就 ...
- 设计模式 ( 十二 ) 职责链模式(Chain of Responsibility)(对象行为)
设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决.不能解决就 ...
- java 之 职责链模式(大话设计模式)
目前很多OA办公自动化软件,加快了办公效率,简化流程.相信很多小伙伴都用过.笔者了解到的大多数办公软件底层实现流程大多数采用的都是Activity或者是JBPM框架. 今天笔者要说的也是类似于流程的一 ...
- java设计模式-----18、职责链模式
概念: Chain of Responsibility(CoR)模式也叫职责链模式.责任链模式或者职责连锁模式,是行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的 ...
- JAVA设计模式之【职责链模式】
职责链模式 专门处理请求链式传递的模式 角色 Handler抽象处理者 ConcreteHandler具体处理者 在职责链模式中,很多对象由每一个对象对其下家的引用而连接成一条链,请求在这条链上传递, ...
- 大话设计模式Python实现-职责链模式
职责链模式(Chain Of Responsibility):使多个对象都有机会处理请求,从而避免发送者和接收者的耦合关系.将对象连成链并沿着这条链传递请求直到被处理 下面是一个设计模式的demo: ...
- C#设计模式系列:职责链模式(Chain of Responsibility)
1.职责链模式简介 1.1>.定义 职责链模式是一种行为模式,为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求.将这些对象连接成一条链,并沿着这条链传递该请求,直到有一个对 ...
- 设计模式入门之职责链模式Chain Of Responsibility
//职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. //实例:申请费用的功能,不同金额的费 ...
随机推荐
- 一天一个Java基础——泛型
这学期的新课——设计模式,由我仰慕已久的老师传授,可惜思维过快,第一节就被老师挑中上去敲代码,自此在心里烙下了阴影,都是Java基础欠下的债 这学期的新课——算法设计与分析,虽老师不爱与同学互动式的讲 ...
- 【打表】HDOJ-2089-不要62
[题目链接:HDOJ-2089] 多组测试数据,所以可以先算出符合条件的所有数保存数组中,输入时则直接遍历数组. #include<iostream> #include<cstrin ...
- Struts2中通配符
1.Struts2中通配符可通过请求的url路径来确定包.类.方法.返回值名. 如 <action name="*_*_*_*" class="cn.javass. ...
- linux中waitpid及wait的用法
wait(等待子进程中断或结束) 表头文件 #include<sys/types.h> #include<sys/wait.h> 定义函数 pid_t wa ...
- RecordWriter接口解析
RecordWriter是将Map/Reduce结果(Key-Value)输出到文件系统中. /** * <code>RecordWriter</code> writes th ...
- Hadoop中的InputFormat解析
1.InputFormat InputFormat是Hadoop平台上Mapreduce输入的规范,仅有两个抽象方法. List<InputSplit> getSplits(), 获取由输 ...
- C/C++面试小知识点
1.static有什么用途. 解答: 在函数体中,一个被声明为静态的变量在这一函数被调用过程中维持其值不变. 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所有函数访问,但不能被模块外其 ...
- sizeof和strlen小结
sizeof和strlen小结 写在前面 之所以要总结一下sizeof和strlen的用法和区别,是因为这些知识可以帮助我们更加深入的理解各种数据结构在内存中的占用情况,也许表面上看好像没有多大用处, ...
- char[]数组与char *指针的区别
char[]数组与char *指针的区别 问题描述 虽然很久之前有看过关于char指针和char数组的区别,但是当时没有系统的整理,到现在频繁遇到,在string,char[], char *中迷失了 ...
- [GRYZ2015]Graph
题目描述 给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v 出发,能到达的编号最大的点. 输入格式 第 1 行,2 个整数 N,M. 接下来 M 行,每行 2 个整数 Ui ...