问题的提出
例如在企业工作的员工请假问题。假设假期少于1天的可由组长决定;多于1天少于两天的,可由车间主任决定;。“组长-主任”构成了一个功能链。
如何更好的处理上述的功能呢?责任链设计模式是一个较好的选择。
类图描述:
抽象处理者(Handler)角色:
定义出一个处理请求的接口或抽象类。可以定义一个方法,以设定和返回对下一节点的引用。图6-3中Handler类的聚合关系给出了具体子类对下一节点的引用,抽象方法handleRequest()规范了子类处理请求的操作。
具体处理者(ConcreteHandler)角色:
具体处理者接到请求后,可以选择将请求处理完毕,或者将请求传给下一节点。由于具体处理者持有对下移节点的引用,因此,如果需要,具体处理者可以访问下一节点。
客户(Client)角色:
负责形成具体处理者的节点功能链,并传递初始请求。
代码:
抽象接口类,定义接口动作和下一个Handler
package com.madman.base.designMode.duty;
public abstract class Handler{
//定义后继处理者变量
private Handler next;
public void setNext(Handler next) {
this.next = next;
}
public Handler getNext() {
return next;
}
//定义抽象请求方法,子类要重写
public abstract boolean handle(Request req);
}
定义主任
package com.madman.base.designMode.duty;
public class ZhuRen extends Handler{
static int limit = 2;
@Override
public boolean handle(Request req) {
if (req.day <= limit) {
System.out.println("ZhuRen agrees the request!");
return true;
}
return getNext().handle(req);
}
}
定义组长
package com.madman.base.designMode.duty;
public class ZuZhang extends Handler{
static int limit = 1;
@Override
public boolean handle(Request req) {
if (req.day <= limit) {
System.out.println("ZuZhang agrees the request!");
return true;
}
return getNext().handle(req);
}
}
设置责任链模式
组长和主任形成了请假批示的责任链
package com.madman.base.designMode.duty;
public class MyChain{
private Handler one = new ZuZhang();
private Handler two = new ZhuRen();
public void createChain() {
one.setNext(two);
}
public void handle(Request req) {
one.handle(req);
}
}
客户端
package com.madman.base.designMode.duty;
public class Client{
public static void main(String[] args) {
Request req = new Request(1);
MyChain mc = new MyChain();
mc.createChain();
Request req2 = new Request(2);
mc.handle(req);
mc.handle(req2);
}
}
结果:
ZuZhang agrees the request!
ZhuRen agrees the request!
上述中的Mychain是通过代码定义的,如果需要添加或者删除还需要修改代码,原则上并不方便,为了方便动态定义,我们稍微改造下,使用反射。
使用反射加载责任链
package com.madman.base.designMode.duty;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Properties;
public class MyChain2{
private Handler[] handler = null;
public void createChain() {
try {
String path = MyChain2.class.getResource("/").getPath();
System.out.println(path);
FileInputStream input = new FileInputStream(path + "com/madman/base/designMode/duty/MyChain.txt");
Properties p = new Properties();
p.load(input);
String[] chains = p.getProperty("chain").split(",");
int n = chains.length;
handler = new Handler[n]; //共有n个处理者
for (int i = 0; i < n; i++) {
//通过反射技术加载各责任链类对象
handler[i] = (Handler) Class.forName(chains[i]).newInstance();
}
for (int i = 0; i < n - 1; i++) {
//设置节点前后关系
handler[i].setNext(handler[i + 1]);
}
input.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void handle(Request req) {
handler[0].handle(req);
}
}
客户端
package com.madman.base.designMode.duty;
public class Client2{
public static void main(String[] args) {
Request req = new Request(1);
MyChain2 mc = new MyChain2();
mc.createChain();
Request req2 = new Request(2);
mc.handle(req);
mc.handle(req2);
}
}