Java学习笔记之--------责任链模式

责任链模式

将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象。

场景

打牌时,轮流出牌;接力赛跑;大学中,奖学金审批;公司中,公文审批。

常见的公司内的请假审批流程:如果请假天数小于3天,主任审批;如果请假天数大于等于3天,小于10天,经理审批;如果大于等于10天,小于30天,总经理审批;如果大于等于30天,则自动拒绝。

责任链模式demo

实现这样一个审批,SCM(Supply Chain Management 供应链管理)系统中,采购审批子系统的设计:

        采购金额小于5万,主任审批;

        采购金额大于等于5万,小于20万,经理审批;

        采购金额大于等于20万,总经理审批。

新建PurchaseRequest类封装采购申请的基本信息(申请人姓名,申请金额,用途);新建一个抽象类Leader,然后主任类Director,经理类Manager,总经理类GeneralManager,代码如下所示。

public class PurchaseRequest {
	//申请人姓名
	private  String empName;
	//申请金额
	private BigDecimal amount;
	//申请原因(用途)
	private String reason;
	public PurchaseRequest(String empName, BigDecimal amount, String reason) {
		this.empName = empName;
		this.amount = amount;
		this.reason = reason;
	}
	public String getEmpName() {
		return empName;
	}
	public void setEmpName(String empName) {
		this.empName = empName;
	}
	public BigDecimal getAmount() {
		return amount;
	}
	public void setAmount(BigDecimal amount) {
		this.amount = amount;
	}
	public String getReason() {
		return reason;
	}
	public void setReason(String reason) {
		this.reason = reason;
	}
}
public abstract class Leader {
	protected String name;
	//责任链上的后继对象
	protected Leader nextLeader;

	public Leader(String name) {
		this.name = name;
	}
	//设定责任链上的后继对象
	public void setNextLeader(Leader nextLeader) {
		this.nextLeader = nextLeader;
	}
	//处理请求的核心的业务方法
	public abstract void handleRequest(PurchaseRequest request);
}
public class Director extends Leader{
	public Director(String name) {
		super(name);
	}
	@Override
	public void handleRequest(PurchaseRequest request) {
		if (request.getAmount().compareTo(new BigDecimal(50000)) == -1){
			System.out.println("员工:" + request.getEmpName() +
					"申请,采购金额" + request.getAmount() +
					",原因(用途):" + request.getReason());
			System.out.println("主任:" + this.name + ",审批通过!");
		} else {
			if (nextLeader != null){
				this.nextLeader.handleRequest(request);
			}
		}
	}
}
public class Manager extends Leader{
	public Manager(String name) {
		super(name);
	}
	@Override
	public void handleRequest(PurchaseRequest request) {
		if (request.getAmount().compareTo(new BigDecimal(50000)) > -1 &&
				request.getAmount().compareTo(new BigDecimal(200000)) == -1){
			System.out.println("员工:" + request.getEmpName() +
					"申请,采购金额" + request.getAmount() +
					",原因(用途):" + request.getReason());
			System.out.println("经理:" + this.name + ",审批通过!");
		} else {
			if (nextLeader != null){
				this.nextLeader.handleRequest(request);
			}
		}
	}
}
public class GeneralManager extends Leader{
	public GeneralManager(String name) {
		super(name);
	}
	@Override
	public void handleRequest(PurchaseRequest request) {
		if (request.getAmount().compareTo(new BigDecimal(200000)) < 1){
			System.out.println("员工:" + request.getEmpName() +
					"申请,采购金额" + request.getAmount() +
					",原因(用途):" + request.getReason());
			System.out.println("总经理:" + this.name + ",审批通过!");
		} else {
			System.out.println("采购金额太大,请分批申请!");
		}
	}
}
public class Client {
	public static void main(String[] args) {
		Leader a = new Director("张主任");
		Leader b = new Manager("李经理");
		Leader c = new GeneralManager("赵总");
		//组织责任链对象的关系
		a.setNextLeader(b);
		b.setNextLeader(c);
		//开始采购金额审批
		PurchaseRequest request = new PurchaseRequest("小明", new BigDecimal(6000),"采购年会礼品!");
		a.handleRequest(request);
	}
}

当申请金额为6000时,结果如图所示:

Java学习笔记之--------责任链模式_第1张图片

如果将金额修改为15万,则运行结果为:

Java学习笔记之--------责任链模式_第2张图片

如果公司设置了一个副总经理的职位,然后修改审批流程为:

        采购金额小于5万,主任审批;

        采购金额大于等于5万,小于10万,经理审批;

        采购金额大于等于10万,小于20万,副总经理审批;

        采购金额大于等于20万,总经理审批。

只需要新增一个副总经理的类,然后将经理类Manager的审批金额上限修改为10万:

public class ViceGeneralManager extends Leader{
	public ViceGeneralManager(String name) {
		super(name);
	}
	@Override
	public void handleRequest(PurchaseRequest request) {
		if (request.getAmount().compareTo(new BigDecimal(100000)) > -1 &&
				request.getAmount().compareTo(new BigDecimal(200000)) == -1){
			System.out.println("员工:" + request.getEmpName() +
					"申请,采购金额" + request.getAmount() +
					",原因(用途):" + request.getReason());
			System.out.println("副总经理:" + this.name + ",审批通过!");
		} else {
			if (nextLeader != null){
				this.nextLeader.handleRequest(request);
			}
		}
	}
}
public class Client {
	public static void main(String[] args) {
		Leader a = new Director("张主任");
		Leader b = new Manager("李经理");
		Leader c = new ViceGeneralManager("孙副总");
		Leader d = new GeneralManager("赵总");
		//组织责任链对象的关系
		a.setNextLeader(b);
		b.setNextLeader(c);
		c.setNextLeader(d);
		//开始采购金额审批
		PurchaseRequest request = new PurchaseRequest("小明", new BigDecimal(150000),"采购年会礼品!");
		a.handleRequest(request);
	}
}

则运行结果为:

Java学习笔记之--------责任链模式_第3张图片

可以看到,当申请金额为15万时,原来由经理审批,现在由副总经理审批,符合需求。

由于责任链的创建完全在客户端,因此新增新的具体处理类对原有类库没有任何影响,只需要添加新类,然后在客户端调用时添加即可。符合开闭原则。

类图

idea自动生成的类图如下所示:

Java学习笔记之--------责任链模式_第4张图片

非链表方式实现责任链

以上为链表方式定义职责链的demo。还可以用非链表方式实现职责链。

通过集合、数组生成责任链模式更加实用。实际上,很多项目中,每个具体的handler并不是由开发团队定义的,而是项目上线后由外部单位追加的,所以使用链表方式定义COR链就很困难。

开发中常见的场景

Java中,异常机制就是一种责任链模式。一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch。

Javascript语言中,事件的冒泡和捕获机制。Java语言中,事件的处理采用观察者模式。

Servlet开发中,过滤器的链式处理。

Struts2中,拦截器的调用也是典型的责任链模式。

 

以上为责任链模式的学习笔记,此文章为尚学堂视频的学习笔记+自己总结。

你可能感兴趣的:(设计模式)