职责链

1,问题定义

客户端发起一个请求,会有多个对象来处理,将处理对象连成一个“链”,这个链可认为是“处理流程”,链上的每个处理对象有不同的处理逻辑,由链上的符合条件的对象来处理。这么做的好处是:请求和处理对象解耦,处理流程可以变换,处理对象可替换。


2,实现步骤

定义一个处理请求的抽象类,定义处理请求的抽象方法,定义一个可以设置另一个处理对象的方法(即链上的下一个处理节点)。


示例代码(假设情景:员工向领导申请经费,不同级别的领导有不同的最高限额授权,处理流程为先给项目经理,再给部门经理,最后给总经理)

/**
 * 处理请求的抽象类
 * @author Abner
 *
 */
abstract class Handler{
	protected Handler handler = null;
	
	/**
	 * 用于接收职责链上的下一个处理节点
	 * @param handler
	 */
	public void setHandler(Handler handler){
		this.handler = handler;
	}
	
	/**
	 * 处理请求的业务方法
	 * @param user
	 * @param fee
	 * @return
	 */
	protected abstract String handleRequest(String user,double fee);
}

/**
 * 具体的请求处理类,项目经理
 * @author Abner
 *
 */
class ProjectManager extends Handler{

	@Override
	protected String handleRequest(String user, double fee) {
		String str = "";
		
		if(fee <= 500){
			if("小张".equals(user)){
				str = "项目经理允许 "+user+" 申请的经费 "+fee;
			}else{
				str = "项目经理不允许 "+user+" 申请的经费 "+fee;
			}
		}else{
			if(this.handler != null){
				str = this.handler.handleRequest(user, fee);
			}
		}
		
		return str;
	}
	
}

/**
 * 具体的请求处理类,部门经理
 * @author Abner
 *
 */
class DepartmentManager extends Handler{
	
	@Override
	protected String handleRequest(String user, double fee) {
		String str = "";
		
		if(fee <= 1000){
			if("小张".equals(user)){
				str = "部门经理允许 "+user+" 申请的经费 "+fee;
			}else{
				str = "部门经理不允许 "+user+" 申请的经费 "+fee;
			}
		}else{
			if(this.handler != null){
				str = this.handler.handleRequest(user, fee);
			}
		}
		
		return str;
	}
	
}

/**
 * 具体的请求处理类,总经理
 * @author Abner
 *
 */
class GeneralManager extends Handler{
	
	@Override
	protected String handleRequest(String user, double fee) {
		String str = "";
		
		if("小张".equals(user)){
			str = "总经理允许 "+user+" 申请的经费 "+fee;
		}else{
			str = "总经理不允许 "+user+" 申请的经费 "+fee;
		}
		
		return str;
	}
	
}

	public static void main(String[] args) {
		Handler hg = new GeneralManager();
		Handler hd = new DepartmentManager();
		Handler hp = new ProjectManager();
		
		hd.setHandler(hg);
		hp.setHandler(hd);
		
		p(hp.handleRequest("小张", 300));
		p(hp.handleRequest("小李", 300));
		
		p(hp.handleRequest("小张", 800));
		p(hp.handleRequest("小李", 800));
		
		p(hp.handleRequest("小张", 1200));
		p(hp.handleRequest("小李", 1200));
	}
	
	static void p(String s){
		System.out.println(s);
	}

输出

项目经理允许 小张 申请的经费 300.0
项目经理不允许 小李 申请的经费 300.0
部门经理允许 小张 申请的经费 800.0
部门经理不允许 小李 申请的经费 800.0
总经理允许 小张 申请的经费 1200.0
总经理不允许 小李 申请的经费 1200.0

3,认识职责链

 3.1,如何构建链

按照实现的地方可以分为:在客户端发出请求前,组合职责链,称为外部链。在Handler里面实现链的组合,称为内部链。在处理对象中,这要求处理对象不仅要处理业务,还要对整个业务流程熟悉。

  3.2,谁来处理

由职责链中符合条件的那个对象处理,如果该请求被处理了,那请求就到处为止。如果整个链中没有合适的对象,那该请求就不会被处理了。

  3.3,处理多种请求

设计时应该考虑到未来功能的扩展,比如会有多种请求。对于多种请求,可以在接口中分别定义多个方法,每种方法对应一种请求,但这种方式的缺点是每次扩展业务,都需要改接口,而且接口对应的实现类也需要改,这种方式不靠谱。另外的方式是,在接口中定义一个“通用”的方法用来处理请求,不论什么样的请求都用这个方法,将请求的业务参数封装到一个专门的请求类中,在类中定义请求的类型,在接口的实现类中针对不同类型的请求实现不同,当新增请求类型了,那就写一个之前的接口实现类的子类,在子类中重写业务方法。


示例:

当只有一个业务类型时

/**
 * 处理请求的抽象类
 * @author Abner
 *
 */
abstract class Handler{
	protected Handler handler = null;
	
	/**
	 * 用于接收职责链上的下一个处理节点
	 * @param handler
	 */
	public void setHandler(Handler handler){
		this.handler = handler;
	}
	
	/**
	 * 处理请求的业务方法
	 * @param user
	 * @param fee
	 * @return
	 */
	protected abstract String handleRequest(Request request);
}

/**
 * 具体的请求处理类,项目经理
 * @author Abner
 *
 */
class ProjectManager extends Handler{

	@Override
	protected String handleRequest(Request request) {
		String str = "";
		
		if(request.getType() == Request.FOOD_FEE){
			if(request.getFee() <= 500){
				if("小张".equals(request.getUser())){
					str = "项目经理允许 "+request.getUser()+" 申请的经费 "+request.getFee();
				}else{
					str = "项目经理不允许 "+request.getUser()+" 申请的经费 "+request.getFee();
				}
			}else{
				if(this.handler != null){
					str = this.handler.handleRequest(request);
				}
			}
		}
		
		return str;
	}
	
}


/**
 * 具体的请求处理类,部门经理
 * @author Abner
 *
 */
class DepartmentManager extends Handler{
	
	@Override
	protected String handleRequest(Request request) {
		String str = "";
		
		if(request.getType() == Request.FOOD_FEE){
			if(request.getFee() <= 1000){
				if("小张".equals(request.getUser())){
					str = "部门经理允许 "+request.getUser()+" 申请的经费 "+request.getFee();
				}else{
					str = "部门经理不允许 "+request.getUser()+" 申请的经费 "+request.getFee();
				}
			}else{
				if(this.handler != null){
					str = this.handler.handleRequest(request);
				}
			}
		}
		
		return str;
	}
	
}


/**
 * 具体的请求处理类,总经理
 * @author Abner
 *
 */
class GeneralManager extends Handler{
	
	@Override
	protected String handleRequest(Request request) {
		String str = "";
		
		if(request.getType() == Request.FOOD_FEE){
			if("小张".equals(request.getUser())){
				str = "总经理允许 "+request.getUser()+" 申请的经费 "+request.getFee();
			}else{
				str = "总经理不允许 "+request.getUser()+" 申请的经费 "+request.getFee();
			}
		}
		
		return str;
	}
	
}

/**
 * 请求类,封装了请求数据
 * @author Abner
 *
 */
class Request{
	public static int FOOD_FEE = 1;
	public static int TRAVEL_FEE = 2;
	
	int type;
	String user;
	double fee;
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	public String getUser() {
		return user;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public double getFee() {
		return fee;
	}
	public void setFee(double fee) {
		this.fee = fee;
	}
	
}

当增加了需求

class ProjectManager2 extends ProjectManager{
	@Override
	protected String handleRequest(Request request) {
		String str = "";
		if(request.getType() == Request.TRAVEL_FEE){ //新的业务需求
			if(request.getFee() <= 500){
				str = "项目经理同意 "+request.getUser()+" 差旅费申请 "+request.getFee();
			}else{
				if(this.handler != null){
					str = this.handler.handleRequest(request);
				}
			}
		}else{ //其他的需求交给父类处理
			str = super.handleRequest(request);
		}
		
		return str;
	}
}

class GeneralManager2 extends GeneralManager{
	@Override
	protected String handleRequest(Request request) {
		String str = "";
		if(request.getType() == Request.TRAVEL_FEE){ //新的业务需求
			if(request.getFee() <= 5000){
				str = "总经理同意 "+request.getUser()+" 差旅费申请 "+request.getFee();
			}else{
				if(this.handler != null){
					str = this.handler.handleRequest(request);
				}
			}
		}else{ //其他的需求交给父类处理
			str = super.handleRequest(request);
		}
		
		return str;
	}
}


class DepartmentManager2 extends DepartmentManager{
	@Override
	protected String handleRequest(Request request) {
		String str = "";
		if(request.getType() == Request.TRAVEL_FEE){ //新的业务需求
			if(request.getFee() <= 1000){
				str = "部门经理同意 "+request.getUser()+" 差旅费申请 "+request.getFee();
			}else{
				if(this.handler != null){
					str = this.handler.handleRequest(request);
				}
			}
		}else{ //其他的需求交给父类处理
			str = super.handleRequest(request);
		}
		
		return str;
	}
}

客户端调用

	public static void main(String[] args) {
		Handler hg = new GeneralManager2();
		Handler hd = new DepartmentManager2();
		Handler hp = new ProjectManager2();
		
		hd.setHandler(hg);
		hp.setHandler(hd);
		
		Request req = new Request();
		req.setFee(200);
		req.setType(Request.FOOD_FEE);
		req.setUser("小丽");
		
		System.out.println(hp.handleRequest(req));
		
		Request req2 = new Request();
		req2.setFee(2000);
		req2.setType(Request.TRAVEL_FEE);
		req2.setUser("小五");
		
		System.out.println(hp.handleRequest(req2));
	}

输出

项目经理不允许 小丽 申请的经费 200.0
总经理同意 小五 差旅费申请 2000.0

这种方式的缺点是,客户端得知道每种类型的请求对应的业务处理类型,还有,没增加一种请求都写一个新的子类,要么类层次过多,要么粒度太细。

   3.4,功能链

标准的职责链是当请求被链中的一个节点处理后,整个流程就结束了。现在扩展下,可以将业务中一系列功能拆分成多个步奏,每个步奏都封装在一个处理节点里,处理流程的要从头走到尾才结束。与web中的Filter类似,过了一个Filter,过另一个Filter,直到结束。


这种方式的缺点是,客户端得知道每种类型的请求对应的业务处理类型,还有,没增加一种请求都写一个新的子类,要么类层次过多,要么粒度太细。



所谓职责链,不过是将一系列操作,这些可能是平行的(标准的职责链),也可能是相互依赖的(功能链),将其他分离出来,抽象一个统一的接口,每步操作都实现这个接口,并且提供将这些步骤连接起来的方式。由此获得的好处是,这些操作的顺序可以动态的组合(当业务流程变化时),当其中某个操作需要修改或替换时,也很容易可以实现。(分离职责,动态组合)
所谓职责链,不过是将一系列操作,这些可能是平行的(标准的职责链),也可能是相互依赖的(功能链),将其他分离出来,抽象一个统一的接口,每步操作都实现这个接口,并且提供将这些步骤连接起来的方式。由此获得的好处是,这些操作的顺序可以动态的组合(当业务流程变化时),当其中某个操作需要修改或替换时,也很容易可以实现。(分离职责,动态组合)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值