责任链模式(Java版)

306 阅读3分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

项目背景

小明操作公司的采购员,需要去采购一批电脑,通过对市场的调研之后,需要提交申请走审批流程拨款购买。审批的决策因素是采用电脑的总价。小于5000,组长审批就ok了,5000-10000需要部长审批,10000-50000需要副总裁审批,50000以上需要总裁审批。

考虑到扩展性,我们下面思考下如何设计?

第一,影响决策因素:价格

第二,决策级别:组长、部长、副总、总裁

接下来,我们责任链模式隆重登场了。

什么是责任链模式?

责任链模式为请求创建了一个接收者对象的链。通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

责任链的意图

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

主要解决的问题

职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

代码示例

下面示例代码走起,首先定义采购对象:

// 采购
public class PurchaseRequest {

    // 采购类型
    private int type = 0;
    // 采购数量
    private int number = 0;
    // 采购单价
    private float price = 0;
    // 采购ID
    private int id = 0;

    public PurchaseRequest(int type, int number, float price) {
        this.type = type;
        this.number = number;
        this.price = price;
    }

    public int getType() {
        return type;
    }

    public float getSum() {
        return number * price;
    }

    public int getId() {
        return (int) (Math.random() * 1000);
    }

}

然后抽象出来一个审批父类:

@Getter
@Setter
public abstract class Approver {

    // 下一个审批者
    protected Approver successor;

    private String name;

    public Approver(String name) {
        this.name=name;
    }

    public abstract void processRequest(PurchaseRequest request);

}

下面依次实现组长、部长、副总裁、总裁审批:

package com.lgd.design.chain;

// 组审批
public class GroupApprover extends Approver {

    public GroupApprover(String Name) {
        super(Name + " GroupLeader");
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getSum() < 5000) {
            System.out.println("**This request " + request.getId() + " will be handled by " + this.getName() + " **");
        } else {
            successor.processRequest(request);
        }
    }
}
package com.lgd.design.chain;

// 部门审批
public class DepartmentApprover extends Approver {

	public DepartmentApprover(String Name) {
		super(Name + " DepartmentLeader");
	}

	@Override
	public void processRequest(PurchaseRequest request) {
		if ((5000 <= request.getSum()) && (request.getSum() < 10000)) {
			System.out.println("**This request " + request.getId() + " will be handled by " + this.getName() + " **");
		} else {
			successor.processRequest(request);
		}
	}

}
package com.lgd.design.chain;

// 副总裁审批
public class VicePresidentApprover extends Approver {

	public VicePresidentApprover(String name) {
		super(name + " Vice President");
	}

	@Override
	public void processRequest(PurchaseRequest request) {
		if ((10000 <= request.getSum()) && (request.getSum() < 50000)) {
			System.out.println("**This request " + request.getId() + " will be handled by " + this.getName() + " **");
		} else {
			successor.processRequest(request);
		}
	}

}
package com.lgd.design.chain;

// 总裁审批
public class PresidentApprover extends Approver {

    public PresidentApprover(String Name) {
        super(Name + " President");

    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (50000 <= request.getSum()) {
            System.out.println("**This request " + request.getId() + " will be handled by " + this.getName() + " **");
        } else {
            successor.processRequest(request);
        }
    }

}

最后测试审批流程:

package com.lgd.design.chain;


public class MainTest {

    public static void main(String[] args) {


        Approver groupApprover = new GroupApprover("Tom");
        Approver departmentApprover = new DepartmentApprover("Jerry");
        Approver vicePresidentApprover = new VicePresidentApprover("Kate");
        Approver presidentApprover = new PresidentApprover("Bush");
        groupApprover.setSuccessor(vicePresidentApprover);
        departmentApprover.setSuccessor(presidentApprover);
        vicePresidentApprover.setSuccessor(departmentApprover);
        presidentApprover.setSuccessor(groupApprover);

        vicePresidentApprover.processRequest(new PurchaseRequest(1, 100, 40));
        vicePresidentApprover.processRequest(new PurchaseRequest(2, 200, 40));
        vicePresidentApprover.processRequest(new PurchaseRequest(3, 300, 40));
        vicePresidentApprover.processRequest(new PurchaseRequest(4, 400, 140));

    }


}

运行结果:

**This request 331 will be handled by Tom GroupLeader **

**This request 504 will be handled by Jerry DepartmentLeader **

**This request 309 will be handled by Kate Vice President **

**This request 473 will be handled by Bush President **

总结

优点:

  • 将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求
  • 可以简化对象,因为它无须知道链的结构
  • 可以动态地增加或删减处理请求的链结构

缺点:

  • 请求从链的开头进行遍历,对性能有一定的损耗
  • 并不保证请求一定被处理

适用场合:

  • 有多个对象可以处理一个请求
  • 不明确接收者的情况
  • 有序、无序链,线型、树形、环形链

责任链模式和状态模式主要区别:

  • 责任链模式注重请求的传递
  • 状态模式注重对象状态的转换