• 15、设计模式之责任链模式


    责任链模式

    顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

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

    介绍

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

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

    何时使用: 在处理消息的时候以过滤很多道。

    如何解决: 拦截的类都实现统一接口。

    关键代码: Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。

    应用实例:

    1. JS 中的事件冒泡。
    2. spring 拦截器。
    3. JAVA WEB 中 Apache Tomcat 对 Encoding 的处理
    4. Struts2 的拦截器

    优点:

    1. 降低耦合度。它将请求的发送者和接收者解耦。
    2. 简化了对象。使得对象不需要知道链的结构。
    3. 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
    4. 增加新的请求处理类很方便。

    缺点:

    1. 不能保证请求一定被接收。
    2. 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
    3. 可能不容易观察运行时的特征,有碍于除错。

    使用场景:

    1. 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
    2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
    3. 可动态指定一组对象处理请求。

    注意事项:JAVA WEB 中遇到很多应用。

    主要涉及到以下几个核心角色:

    抽象处理者(Handler):

    定义一个处理请求的接口,通常包含一个处理请求的方法(如 handleRequest)和一个指向下一个处理者的引用(后继者)。
    具体处理者(ConcreteHandler):

    实现了抽象处理者接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者。
    客户端(Client):
    创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。

    代码实现

    以公司中的OA申请为例,有各种申请:请假、离职、团建、加班、购买设备等;不同申请需要的权限不一样,需要审批的人不一样。

    定义申请类

    /**
     * 申请
     */
    public class Petition {
        /**
         * 标题
         */
        private String name;
    
        /**
         * 内容
         */
        private String content;
    
        private Type type;
    
        /**
         * 申请人
         */
        private String asker;
    
        public Petition(String name, String content, String asker, Type type) {
            this.name = name;
            this.content = content;
            this.asker = asker;
            this.type = type;
        }
    
        public String getName() {
            return name;
        }
    
        public String getContent() {
            return content;
        }
    
        public Type getType() {
            return type;
        }
    
        public String getAsker() {
            return asker;
        }
    
        public enum Type {
            /**
             * 请假
             */
            LEAVE,
            /**
             * 加班
             */
            OVERTIME,
            /**
             * 离职
             */
            OFF_WORK,
            /**
             * 团建
             */
            TRAVEL,
            /**
             * 购买设备
             */
            BUY_EQUIPMENT,
            /**
             * 其他
             */
            OTHER
        }
    }
    
    

    定义抽象职位

    
    /**
     *  职位
     */
    public abstract class Position {
    
        private Position nextPosition;
    
        public Position getNextPosition() {
            return this.nextPosition;
        }
    
        public Position nextPosition(Position nextPosition) {
            this.nextPosition = nextPosition;
            return this.nextPosition;
        }
    
        public abstract boolean handle(Petition petition);
    
    }
    

    定义小组长,小组长只能审批类型为其他的申请

    /**
     * 小组长
     */
    public class TeamLeader extends Position{
        @Override
        public boolean handle(Petition petition) {
            if (petition.getType() == Petition.Type.OTHER){
                System.out.println("小组长审批" + petition.getName() + "通过");
                return true;
            }
            //小组长没有权限,提交给上一级审批
            return getNextPosition().handle(petition);
        }
    }
    
    

    定义经理,经理能够审批加班,请假,团建的申请

    /**
     * 项目经理
     */
    public class Manager extends Position{
    
        @Override
        public boolean handle(Petition petition) {
            if (petition.getType() == Petition.Type.OVERTIME
                || petition.getType() == Petition.Type.LEAVE
                    || petition.getType() == Petition.Type.TRAVEL){
                System.out.println("项目经理审批" + petition.getName() + "通过");
                return true;
            }
            //项目经理没有权限,提交给上一级审批
            return getNextPosition().handle(petition);
        }
    }
    

    定义总经理,能够审批购买设备,离职的申请

    /**
     * 总经理
     */
    public class GeneralManager extends Position{
        @Override
        public boolean handle(Petition petition) {
            if (petition.getType() == Petition.Type.BUY_EQUIPMENT
                    ||petition.getType() == Petition.Type.OFF_WORK){
                System.out.println("总经理经理审批" + petition.getName() + "通过");
                return true;
            }else {
                System.out.println("总经理经理审批" + petition.getName() + "不通过");
                return false;
            }
        }
    }
    

    客户端

    public class Client {
        public static void main(String[] args) {
            Manager manager = new Manager();
            TeamLeader teamLeader = new TeamLeader();
            GeneralManager generalManager = new GeneralManager();
    
            //小组长上级项目经理,项目经理上级总经理
            teamLeader.nextPosition(manager).nextPosition(generalManager);
    
            teamLeader.handle(new Petition("Buy equipment", "I need to buy a new computer", "Jim", Petition.Type.BUY_EQUIPMENT));
    
            teamLeader.handle(new Petition("Leave", "I need to leave", "Jim", Petition.Type.LEAVE));
    
            teamLeader.handle(new Petition("Overtime", "I need to work overtime", "Jim", Petition.Type.OVERTIME));
    
            teamLeader.handle(new Petition("Off work", "I need to go off work", "Jim", Petition.Type.OFF_WORK));
    
            teamLeader.handle(new Petition("Travel", "I need to travel", "Jim", Petition.Type.TRAVEL));
    
            teamLeader.handle(new Petition("Other", "I need to do something else", "Jim", Petition.Type.OTHER));
    
    
        }
    }
    
    
  • 相关阅读:
    1. 算法简介
    Dubbo基本原理
    信息系统项目管理师必背核心考点(五十六)配置控制委员会(CCB)的工作
    【block是1个数据类型 Objective-C语言】
    差分(一维+二维超详细)
    Java静态代理模式
    HTTP状态管理:Cookie&Session
    英语六级-day8
    Linux基本使用
    ThreeJS-3D教学二基础形状展示
  • 原文地址:https://blog.csdn.net/maligebazi/article/details/139109097