设计模式之责任链模式

一、概念

是一个请求有多个对象来处理,这些对象是一条链,但具体由哪个对象来处理,根据条件判断来确定,如果不能处理会传递给该链中的下一个对象,直到有对象处理它为止。

二、使用场景

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定。
  • 在不明确指定接受者的情况下,向多个对象中的一个提交一个请求。
  • 可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求。
  • 常见如ERP中的审批流程

三、不采用责任链设计模式

如采购申请流程:小于3000由项目经理审批,大于3000小于5000需人事主管审批,大于5000需总经理审批。则不采用责任链设计模式,则代码如下

public class OrdinaryApprover {
    private void processRequest(PurchaseRequest request) {
        if (request.getPrice() <= 3000) {
            //项目经理审批
            this.managerApprove(request);
        } else if (request.getPrice() <= 5000) {
            //人事主管审批
            this.hrApprove(request);
        } else {
            //总经理审批
            this.headerApprove(request);
        }
    }

    private void headerApprove(PurchaseRequest request) {

    }

    private void hrApprove(PurchaseRequest request) {
    }

    private void managerApprove(PurchaseRequest request) {
    }
}

 上述方案存在的问题:

1.  OrdinaryApprover类随着审批流程的复杂会越来越庞大,各个级别的审批方法都集中在一个类中,违反了"单一职责原则",测试和维护难度大。

2.  当需要增加一个新的审批级别或调整任何一级的审批金额和审批细节(例如将人事主管的审批额度改为6000元)时,都必须修改源代码并进行严格测试;此外,如果需要移除某一级别(例如金额为10000元及以上的采购单直接由总经理审批,不再设人事主管一职)时也必须对源代码进行修改,违反了“开闭原则”;

3. 审批流程的设置缺乏灵活性,现在的审批流程是“项目经理–>人事主管–>总经理”,如果需要改为“项目经理–>总经理–>董事会”,在此方案中只能通过修改源代码来实现,客户端无法定制审批流程

四、采用设计模式

采购申请单实体类

public class PurchaseRequest {
    /**采购编号**/
    private String purId;

    /**采购价格**/
    private double price = 0;

    public String getPurId() {
        return purId;
    }

    public void setPurId(String purId) {
        this.purId = purId;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public PurchaseRequest(String purId, double price) {
        this.purId = purId;
        this.price = price;
    }
}

 审批者公共类

public abstract class Approver {
    private Approver nextApprover;

    /**
     * 审批单据
     * @param purchaseRequest
     */
    abstract void processRequest(PurchaseRequest purchaseRequest);

    protected Approver getNextApprover() {
        return nextApprover;
    }

    protected void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }
}

项目经理

public class ManagerApprover extends Approver {

    @Override
    void processRequest(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() <= 3000) {
            System.out.println("项目经理审批通过!");
        } else if (this.getNextApprover() != null) {
            this.getNextApprover().processRequest(purchaseRequest);
        }
    }
}

人事主管

public class HRApprover extends Approver {

    @Override
    void processRequest(PurchaseRequest purchaseRequest) {
        double price = purchaseRequest.getPrice();
        if (price > 3000 && price <= 5000) {
            System.out.println("人事经理审批通过!");
        } else if (this.getNextApprover() != null) {
            this.getNextApprover().processRequest(purchaseRequest);
        }
    }
}

总经理

public class HeaderApprover extends Approver {
    @Override
    void processRequest(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() > 5000) {
            System.out.println("总经理审批通过!");
        } else if (this.getNextApprover() != null) {
            this.getNextApprover().processRequest(purchaseRequest);
        }
    }
}

测试:

public class MainTest {
    public static void main(String[] args) {
        PurchaseRequest request = new PurchaseRequest("PU0001", 12000);

        ManagerApprover managerApprover = new ManagerApprover();
        HRApprover hrApprover = new HRApprover();
        HeaderApprover headerApprover = new HeaderApprover();

        managerApprover.setNextApprover(hrApprover);
        hrApprover.setNextApprover(headerApprover);

        managerApprover.processRequest(request);
        hrApprover.processRequest(request);
        headerApprover.processRequest(request);
    }
}

posted on 2020-10-03 18:29  lvguoliang(学无止境)  阅读(1566)  评论(0)    收藏  举报