设计模式之职责链模式

职责链模式

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。

下面模拟以下场景:你想向公司领导(经理<总监<总经理)提出请假或者加薪。不过你提出某些请求经理或者总监无权批准,得向总经理上报,让总经理定夺。

首先我们创建对象让它提供这个请求服务。因此我们得创建一个请求类。

class Request {
    private String requestType; //申请类别
    private String requestContent; //申请内容
    private int number; //申请数量

    public Request(String requestType, String requestContent, int number) {
        this.requestType = requestType;
        this.requestContent = requestContent;
        this.number = number;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public void setRequestContent(String requestContent) {
        this.requestContent = requestContent;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getRequestType() {
        return requestType;
    }

    public String getRequestContent() {
        return requestContent;
    }

    public int getNumber() {
        return number;
    }
}

接下来创建对象来提供对请求做出处理的服务。因此我们创建一个管理者类。

class Manger {
    private String name;

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

    public void getResult(String managerLevel, Request request){
        //经理可以批2天以下的假,管不了加薪
        if(managerLevel == "经理")
            if(request.getRequestType() == "请假" && request.getNumber() <= 2)
                System.out.println(name + ":" + request.getRequestContent()
                        + request.getNumber() + "被批准" );
            else
                System.out.println(name + ":" + request.getRequestContent()
                        + request.getNumber() + "我无权处理" );
            //总监可以批5天以下的假,管不了加薪
        else if(managerLevel == "总监")
            if(request.getRequestType() == "请假" && request.getNumber() <= 5)
                System.out.println(name + ":" + request.getRequestContent()
                        + request.getNumber() + "被批准" );
            else
                System.out.println(name + ":" + request.getRequestContent()
                        + request.getNumber() + "我无权处理" );
            //总经理可以批任意天次的假,和五百以内的加薪。
        else if(managerLevel == "总经理")
            if(request.getRequestType() == "请假")
                System.out.println(name + ":" + request.getRequestContent()
                        + request.getNumber() + "被批准" );
            else if(request.getRequestType() == "加薪" && request.getNumber() <= 500)
                System.out.println(name + ":" + request.getRequestContent()
                        + request.getNumber() + "被批准" );
            else if (request.getRequestType() == "加薪" && request.getNumber() > 500)
                System.out.println(name + ":" + request.getRequestContent()
                        + request.getNumber() + "再说吧" );
    }
}

最后创建一个客户端类,用于提交申请且回馈处理结果。


public class Client {
    public static void main(String[] args) {
        Manger jingli = new Manger("经理");
        Manger zongjian = new Manger("总监");
        Manger zongjingli = new Manger("总经理");

        Request request1 = new Request("请假","小菜请假",2);
        Request request3 = new Request("请假","小菜请假",5);
        Request request2 = new Request("加薪", "小菜加薪", 500);

        jingli.getResult("经理", request1);
        zongjian.getResult("总监", request1);
        zongjingli.getResult("总经理", request1);
        System.out.println();

        jingli.getResult("经理", request3);
        zongjian.getResult("总监", request3);
        zongjingli.getResult("总经理", request3);
        System.out.println();

        jingli.getResult("经理", request2);
        zongjian.getResult("总监", request2);
        zongjingli.getResult("总经理", request2);

    }
}

看看以上代码会发现很多问题。
1.管理者类getResult()方法比较长,分支判断太多。
2.想在管理者类中添加其他管理者(比如项目经理,部门经理什么的)就意味着都需要去修改这个类,这个类承担了太多责任违背了单一职责原则,增加新的管理者需要修改这个类违背了和开放-封闭原则。

从逻辑上讲:我们想要请假是直接去找自己的上级————经理。当我们的上级处理不了了他就会去找他的上级。如此继续直到请假这个请求得到结果。但上述代码并没有体现出这个过程。

那么如何解决这个问题呢?我们看看职责链模式是如何做的。

/*
      创建一个抽象的管理这类,这个类的对象提供两个服务:
      1.处理自己能处理的请求。
      2.将自己不能处理的请求传递给下一级管理者。
*/
abstract class Handler {
    protected  Handler handler;

    //设置下一级管理者
    public void setNextHandler(Handler nextHandler){
        this.handler = nextHandler;
    }

    //处理请求的抽象方法
    public abstract  void HandleRequest(Request request);
}

/*
      创建各级别的管理者,他们都得实现HandleRequest方法来处理请求。
*/
class JingLi extends Handler {
    private String name;

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

    @Override
    public void HandleRequest(Request request) {
        if(request.getNumber() >= 0 && request.getNumber() < 2)
            System.out.println(name + ":" + request.getRequestType() + " " +
                    request.getRequestContent() + " " + request.getNumber() + " " + "批准");
        else //若不能处理当前请求,将请求传递给下一级管理者
            handler.HandleRequest(request);
    }
}

class ZongJian extends Handler {
    private String name;

    public ZongJian(String name) {
        this.name = name;
    }
    @Override
    public void HandleRequest(Request request) {
        if(request.getNumber() >= 2 && request.getNumber() < 5)
            System.out.println(name + ":" + request.getRequestType() + " " +
                    request.getRequestContent() + " " + request.getNumber() + " " +"批准");
        else
            handler.HandleRequest(request);
    }
}

class ZongJingLi extends Handler {
    private String name;

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

    @Override
    public void HandleRequest(Request request) {
        if(request.getRequestType() == "请假")
            if(request.getNumber() > 5)
                System.out.println(name + ":" + request.getRequestType() + " " +
                        request.getRequestContent() + " " + request.getNumber() + " " +"批准");
        if(request.getRequestType() == "加薪")
            if(request.getNumber() <= 1000)
                System.out.println(name + ":" + request.getRequestType() + " " +
                        request.getRequestContent() + " " + request.getNumber() + " " +"批准");
            else if(request.getNumber() > 1000)
                System.out.println(name + ":" + request.getRequestType() + " " +
                        request.getRequestContent() + " " + request.getNumber() + " " +"再说吧");
        else
            handler.HandleRequest(request);
    }
}

/*
     请求类,此类的对象提供请求信息的服务。
*/
class Request {
    private String requestType; //申请类别
    private String requestContent; //申请内容
    private int number; //申请数量

    public Request(String requestType, String requestContent, int number) {
        this.requestType = requestType;
        this.requestContent = requestContent;
        this.number = number;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public void setRequestContent(String requestContent) {
        this.requestContent = requestContent;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getRequestType() {
        return requestType;
    }

    public String getRequestContent() {
        return requestContent;
    }

    public int getNumber() {
        return number;
    }
}

/*
      客户端类:用于提交请求
*/
public class Client {
    public static void main(String[] args) {
        //创建各种请求
        Request request1 = new Request("请假", "小菜请假", 1);
        Request request2 = new Request("请假", "小菜请假", 10);
        Request request3 = new Request("加薪", "小菜加薪", 1000);
        Request request4 = new Request("加薪", "小菜加薪", 1500);

        //创建管理者对象
        Handler jingLi = new JingLi("经理");
        Handler zongJian = new ZongJian("总监");
        Handler zongjingli = new ZongJingLi("总经理");
            
        /*
            将管理者之间的关系链起来(经理<总监<总经理)
        */
        jingLi.setNextHandler(zongJian);
        zongJian.setNextHandler(zongjingli);

        //提交请求。
        /*jingLi.HandleRequest(request1);
        jingLi.HandleRequest(request2);*/
        jingLi.HandleRequest(request2);
        
    }
}

将管理者类做成抽象的,方便我们增加不同的管理者类别(只需继承这个抽象的管理者类,实现HandleRequest()方法即可)。
将管理者关系链起来,当客户提出一个请求时,请求是沿链传递的,直到有一个管理者能处理它。这样做大大降低了耦合度。

posted @ 2020-09-27 22:15  xxgbl  阅读(129)  评论(0)    收藏  举报