美文网首页
行为型模式之责任链模式

行为型模式之责任链模式

作者: BrotherTree | 来源:发表于2019-03-07 16:22 被阅读0次

    在设计模式中,责任链模式是属于行为模式,请求从一个起点开始,沿着任务链依次传递给下一个节点,直到某个节点处理了该请求而结束。

    责任链中的每个节点都有机会去处理该请求,且发送方不需要关心接收方(链)的结构,这样就有效的避免了发送者和接收者之间的耦合。

    在Android中,Touch事件分发流程就是典型的责任链模式,事件沿着Activity、ViewGroup和View传递,直到其中某一方消费了该事件为止。


    image.png
    举个栗子

    公司员工级别:普通员工、部门经理、总经理、老板
    普通员工需要请假,2天需要部门经理批准,5天需要总经理批准,10天需要老板批准。

    首先,编写员工类

    public class Staff {
    
        // 员工需要请假天数所在level
        // 1:10天以内,此时需Boss批准
        // 2:5天以内,此时需GeneralManager批准
        // 3:2天以内,此时需OrdinaryManager批准
        // 其他:谁也不会批准
        private int level;
    
        // 请假描述
        private String request;
    
        public Staff(int level) {
            this.level = level;
            switch (this.level) {
                case 1:
                    this.request = "员工请假10天以内";
                    break;
                case 2:
                    this.request = "员工请假5天以内";
                    break;
                case 3:
                    this.request = "员工请假2天以内";
                    break;
                default:
                    this.request = "员工请假超过10天";
                    break;
            }
        }
    
        // 获取员工需要请假天数所在level
        public int getLevel() {
            return level;
        }
    
        // 请假描述
        public String getRequest() {
            return request;
        }
    }
    

    编写Manger类,此类是一个抽象类

    public abstract class Manager {
    
        // 员工等级
        public static final int BOSS = 1;// 老板
        public static final int GENERAL_MANAGER = 2;// 总经理
        public static final int ORDINARY_MANAGER = 3;// 部门经理
    
        private int level;
    
        private Manager nextManger;
    
        public Manager(int level) {
            this.level = level;
        }
    
        // 设置下一个处理节点
        public void setNextManger(Manager nextManger) {
            this.nextManger = nextManger;
        }
    
        public final void request(Staff staff) {
            // 获取请假等级和当前manager等级进行比较,如果相等,则当前manager有权限批准
            if (staff.getLevel() == level) {
                // 调用子类manager的处理
                response(staff);
            } else {
                // 如果nextManger不为null,即存在下一个处理节点
                if (nextManger != null) {
                    // 下一个处理节点来处理该请求,这里使用了递归调用
                    nextManger.request(staff);
                } else {
                    // 没有下一个处理者
                    System.out.println("项目紧张,无法批准这么多天假期");
                    System.out.println("==========================");
                }
            }
        }
    
        // 抽象方法,需要子类实现
        protected abstract void response(Staff staff);
    }
    

    下面是实现三个Manger的子类

    // 老板
    public class Boss extends Manager {
    
        public Boss() {
            super(Manager.BOSS);
        }
    
        // 处理请求
        @Override
        protected void response(Staff staff) {
            System.out.println("员工问Boss");
            System.out.println(staff.getRequest());
            System.out.println("Boss回答OK");
            System.out.println("==========================");
        }
    }
    
    // 总经理
    public class GeneralManager extends Manager {
    
        public GeneralManager() {
            super(Manager.GENERAL_MANAGER);
        }
    
        // 处理请求
        @Override
        protected void response(Staff staff) {
            System.out.println("员工问GeneralManager");
            System.out.println(staff.getRequest());
            System.out.println("GeneralManager回答OK");
            System.out.println("==========================");
        }
    }
    
    // 部门经理
    public class OrdinaryManager extends Manager {
    
        public OrdinaryManager() {
            super(Manager.ORDINARY_MANAGER);
        }
    
        // 处理请求
        @Override
        protected void response(Staff staff) {
            System.out.println("员工问OrdinaryManager");
            System.out.println(staff.getRequest());
            System.out.println("OrdinaryManager回答OK");
            System.out.println("==========================");
        }
    }
    

    最后是发起员工的请假事宜

    public class TestMain {
    
        public static void main(String[] args) {
    
            // 1...4之间随机数,作为员工请假等级,对应manager的等级
            Random random = new Random();
            ArrayList<Staff> arrayList = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                arrayList.add(new Staff(random.nextInt(4)));
            }
    
            // 三个manager对象
            Manager ordinaryManager = new OrdinaryManager();
            Manager generalManager = new GeneralManager();
            Manager boss = new Boss();
    
            // 设置责任链的下一个处理节点
            // 部门经理之后是总经理
            ordinaryManager.setNextManger(generalManager);
            // 总经理之后是老板
            generalManager.setNextManger(boss);
    
            // 为了体现不同请假等级后的不同处理情况,这里用一个数组来产生多个请求
            for (Staff staff : arrayList) {
                // 开始第一个节点的请求
                ordinaryManager.request(staff);
            }
        }
    }
    

    执行结果(随机)

    员工问OrdinaryManager
    员工请假2天以内
    OrdinaryManager回答OK
    ==========================
    员工问OrdinaryManager
    员工请假2天以内
    OrdinaryManager回答OK
    ==========================
    员工问OrdinaryManager
    员工请假2天以内
    OrdinaryManager回答OK
    ==========================
    员工问GeneralManager
    员工请假5天以内
    GeneralManager回答OK
    ==========================
    员工问OrdinaryManager
    员工请假2天以内
    OrdinaryManager回答OK
    ==========================
    员工问OrdinaryManager
    员工请假2天以内
    OrdinaryManager回答OK
    ==========================
    员工问OrdinaryManager
    员工请假2天以内
    OrdinaryManager回答OK
    ==========================
    项目紧张,无法批准这么多天假期
    ==========================
    员工问GeneralManager
    员工请假5天以内
    GeneralManager回答OK
    ==========================
    项目紧张,无法批准这么多天假期
    ==========================
    
    Process finished with exit code 0
    
    image.png
    角色分析
    • Manager:抽象处理者角色,声明一个处理请求的方法,并保持对下一个处理节点Manager对象的引用
    • Boss:具体的处理者,对请求进行处理,如果不处理就讲请求转发给下一个节点上的处理对象(GeneralManager、OrdinaryManager同Boss)
    优点
    • 降低耦合度,将请求的发送者和接收者解耦,便于拓展,提高代码灵活性。
    • 简化了对象。使得对象不需要知道链的结构。
    • 增强给对象指派责任节点的灵活性,通过改变链内的成员或者调动它们的次 序,允许动态地新增或者删除责任节点。
    缺点
    • 如果责任链太长,或者每条链判断处理的时间太长会影响性能。特别是递归循环的时候。
    • 请求不一定能得到处理,可能会没有对象处理。

    相关文章

      网友评论

          本文标题:行为型模式之责任链模式

          本文链接:https://www.haomeiwen.com/subject/goycpqtx.html