JAVA设计模式---职责链模式

一、职责链应用场景

1.java web filter拦截器的实现,客户端发送的请求会沿着filter拦截器的链式结构传递,进行相应的处理。
2.Java 异常处理机制,可以观察java异常抛出的日志,可以看到异常的抛出是以链式结构层层抛出。
  某场景下,员工向公司请假或者请求涨薪,如果员工先向经理申请,主管表示没有权限,需要总监批准。而员工再向总监请示,总监表示也没有权限,需要总经理授权。模拟这种情景的代码,如果写在一个类中会发现会出现很多的分支结构。而职责链的出现,能够改善这种情况下的代码,而且员工不需要一个一个向上级请示(员工只是提交申请,并不知道是谁处理他的申请),而是系统根据链式结构进行处理,如果当级管理者没有权限处理该事务,则会传递给其上级进行处理,从而实现了代码之间的低耦合。

二、职责链模式定义

  职责链模式(Chain of Responsibility):使多个对象都有机会处理该请求,从而避免请求发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有个对象处理它为止。

三、职责链模式类图

JAVA设计模式---职责链模式_第1张图片
  此类图来自程杰的《大话设计模式》。

四、简单实例

1. 抽象处理者类

package com.cn.itcast.ChainofResponsibility;

/**
 * Created by LJP on 2019/4/21.
 */
public abstract class Handler {
    /**
     * 具体执行者
     */
    protected Handler successor;

    /**
     * 设置继承者
     * @param successor
     */
    public void setSuccessor (Handler successor) {
        this.successor = successor;
    }

    /**
     * 抽象处理方法
     * @param request
     */
    public abstract void HandleRequest(int request);

}

2.实际处理者
  实际处理者有三个。

package com.cn.itcast.ChainofResponsibility;

/**
 * Created by LJP on 2019/4/21.
 */
public class ConcreteHandler1 extends Handler {

    /**
     *
     * @param request
     */
    @Override
    public void HandleRequest(int request) {
        if (request >= 0 && request < 10) {
            System.out.println(this.getClass().getSimpleName() + "---" + request);
        } else if (successor != null){
            successor.HandleRequest(request);
        }
    }
}
package com.cn.itcast.ChainofResponsibility;

/**
 * Created by LJP on 2019/4/21.
 */
public class ConcreteHandler2 extends Handler {

    @Override
    public void HandleRequest(int request) {
        if (request >= 10 && request < 20) {
            System.out.println(this.getClass().getSimpleName() + "---" + request);
        } else if (successor != null){
            successor.HandleRequest(request);
        }
    }
}
package com.cn.itcast.ChainofResponsibility;

/**
 * Created by LJP on 2019/4/21.
 */
public class ConcreteHandler3 extends Handler{

    @Override
    public void HandleRequest(int request) {
        if (request >= 20 && request < 30) {
            System.out.println(this.getClass().getSimpleName() + "---" + request);
        } else {
            System.out.println("该数字无法处理" + "---" + request);
        }
    }
}

3.测试代码

package com.cn.itcast.ChainofResponsibility;

/**
 * Created by LJP on 2019/4/21.
 */
public class test {
    public static void main(String[] args) {
        Handler h1 = new ConcreteHandler1();
        Handler h2 = new ConcreteHandler2();
        Handler h3 = new ConcreteHandler3();
        h1.setSuccessor(h2);
        h2.setSuccessor(h3);

        int[] requests = {2,3,5,11,20,1,35,28};
        for (int i = 0; i < requests.length; i++) {
            h1.HandleRequest(requests[i]);
        }
        System.out.println("执行结束");
    }
}

4.输出结果

ConcreteHandler1---2
ConcreteHandler1---3
ConcreteHandler1---5
ConcreteHandler2---11
ConcreteHandler3---20
ConcreteHandler1---1
该数字无法处理---35
ConcreteHandler3---28
执行结束

Process finished with exit code 0

  根据程序输出可知,请求会随着链的传递而进行处理。注意:在实际处理类中要判断sucessor是否为空,否则如果没有进行h2.setSuccessor(h3)的情况下会出现空指针异常。异常如下:

ConcreteHandler1---3
ConcreteHandler1---5
ConcreteHandler2---11
Exception in thread "main" java.lang.NullPointerException
	at com.cn.itcast.ChainofResponsibility.ConcreteHandler2.HandleRequest(ConcreteHandler2.java:13)
	at com.cn.itcast.ChainofResponsibility.ConcreteHandler1.HandleRequest(ConcreteHandler1.java:17)
	at com.cn.itcast.ChainofResponsibility.test.main(test.java:15)

Process finished with exit code 1

  通过异常信息也可以看出异常的抛出也是链式的结构。可以看到主程序中,客户端只要向h1提出申请,不需要关心是谁帮它处理了请求,这样降低了客户端与服务器之间的耦合度。

五、请假加薪代码实现

1.请求类

package com.cn.itcast.ChainofResponsibility1;

/**
 * 请求实体类,用于存储请求类型,请求内容,请求数量
 * Created by LJP on 2019/4/21.
 */
public class Request {
    private String requestType;

    private String requestContent;

    private Integer number;

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

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

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

    public String getRequestType() {
        return requestType;
    }

    public String getRequestContent() {
        return requestContent;
    }

    public Integer getNumber() {
        return number;
    }
}

2.管理者抽象类

package com.cn.itcast.ChainofResponsibility1;

/**
 * Created by LJP on 2019/4/21.
 */
public abstract class Manager {
    protected String name;

    protected Manager superior;

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

    public void setSuperior(Manager superior) {
        this.superior = superior;
    }

    public abstract void requestApplications(Request request);
}

3.管理者具体类

package com.cn.itcast.ChainofResponsibility1;

/**
 * 经理
 * Created by LJP on 2019/4/21.
 */
public class CommonManager extends Manager {

    public CommonManager(String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType().equals("请假") && request.getNumber() <= 2){
            System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",被批准");
        } else if (superior != null) {
            superior.requestApplications(request);
        }
    } 
}
package com.cn.itcast.ChainofResponsibility1;

/**
 * 总监类
 * Created by LJP on 2019/4/21.
 */
public class Majordomo extends Manager {

    public Majordomo (String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType().equals("请假") && request.getNumber() <= 5){
            System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",被批准");
        } else if (superior != null) {
            superior.requestApplications(request);
        }
    }
}
package com.cn.itcast.ChainofResponsibility1;

/**
 * 总经理类
 * Created by LJP on 2019/4/21.
 */
public class GeneralManager extends Manager{

    public GeneralManager (String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType().equals("请假")){
            System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",被批准");
        } else if (request.getRequestType().equals("加薪") && request.getNumber() <= 500) {
            System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",被批准");
        } else if (request.getRequestType().equals("加薪") && request.getNumber() > 500) {
            System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",再说吧");
        }
    }
}

4.测试类

package com.cn.itcast.ChainofResponsibility1;

/**
 * 测试类
 * Created by LJP on 2019/4/21.
 */
public class test {
    public static void main(String[] args) {
        //创建管理者类
        Manager commonManager = new CommonManager("张经理");
        Manager majordomo = new Majordomo("王总监");
        Manager generalManager = new GeneralManager("马总经理");
        commonManager.setSuperior(majordomo);
        majordomo.setSuperior(generalManager);

        //创建请求
        Request request = new Request();
        request.setRequestType("请假");
        request.setRequestContent("小李请假");
        request.setNumber(1);
        commonManager.requestApplications(request);

        Request request1 = new Request();
        request1.setRequestType("请假");
        request1.setRequestContent("小李请假");
        request1.setNumber(4);
        commonManager.requestApplications(request1);

        Request request2 = new Request();
        request2.setRequestType("加薪");
        request2.setRequestContent("小李请求加薪");
        request2.setNumber(500);
        commonManager.requestApplications(request2);

        Request request3 = new Request();
        request3.setRequestType("加薪");
        request3.setRequestContent("小李请求加薪");
        request3.setNumber(1000);
        commonManager.requestApplications(request3);

        System.out.println("执行结束");
    }
}

5.测试结果

张经理---小李请假---1,被批准
王总监---小李请假---4,被批准
马总经理---小李请求加薪---500,被批准
马总经理---小李请求加薪---1000,再说吧
执行结束

Process finished with exit code 0

  客户端的申请都是通过经理进行发起,但具体的操作者对于客户端来说并不知道。注意在编写具体实现类一定要重写构造方法,这是因为管理者抽象类中有有参构造方法。

六、模式总结

  优点:1.降低应用程序之间耦合。2.将多种判定分散到各个处理类中,程序更加清晰,各类职责更加明确
  缺点:1.在找到正确的处理对象之前,所有条件判定都要执行一遍,当责任链过长,可能会影响性能问题。2.可能会造成某个请求不被处理,所以在程序设计时需要考虑全面。
  除了上述关于一个请求可能需要多级审批的情况下,另外,if-else判断较多的情况下也可考虑责任链模式。这里奉上github项目地址,仅供参考。

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