Java设计模式(5)之责任链模式学习总结

    在日常生活中,我们如果仔细观察的话,很多事情都蕴含着责任链模式的思想;比如某个人去售楼处买房,对销售人员提出打折的要求,如果折扣比较 
小,销售人员有权给予该购买者提出的折扣优惠,就可以直接答应该请求;如果折扣过大,销售人员无权答应,则会想他的上司——销售组长询问, 
如果销售组长有权答应该折扣,则直接回复可以,并将房子售卖给客户;以此类推,直至该折扣请求被处理,客户得到相应的答复,该事件结束。

    再比如,我们曾经玩过的抛手绢、击鼓传花等游戏,都有责任链模式的影子;总的来说,责任链模式就是:将接收者对象连城一条链,将对应的请求
在该链上进行传递,直至有接收者对象处理了该请求;这种通过允许更多接收者对象有机会对请求进行处理,来避免请求者和接收者之间的耦合; 
    其中,责任链模式中的“责任链”源于在链上的每个处理者都有责任去处理在链上传递的请求,同时,处理者对应不同等级的请求,相应地有处理请求
的权限;
    另外,在上面的例子中,购房者不需要知道谁处理了他的折扣请求,击鼓传花中,击鼓者,也不需要知道是谁拿到花并进行节目表演,这就解释了 
上面说的请求者和接收处理者之间的去耦合是怎么一回事。  

    下面将以生活中公司中职员请假的流程作为示例,采用责任链模式进行代码的设计,通过直观的讲解来阐述责任链模式的设计思想;
    package com.pattern.handler;
    /**
     * 假期申请接收者对应的抽象类,负责处理工作人员的假期申请
     */
    public abstract class LeaveHandler
    {
        /**
         * 直接后继管理人员,用于传递请求
         */
        protected LeaveHandler successor;

        public void setSuccessor(LeaveHandler successor) 
        {
            this.successor = successor;
        }
        /**
         * 处理假期申请
         */
        public abstract void processLeave(int days);
    }


    package com.pattern.handler;
    /**
     * 组长类, 可以批准2天以内的假期申请
     */
    public class GroupLeader extends LeaveHandler 
    {
        @Override
        public void processLeave(int days) 
        {
            if(days<=2)
            {
                System.out.println(this.getClass().getName()+"批准了"+days+"天假");
            }
            else
            {
                successor.processLeave(days);
            }
        }
    }


    package com.pattern.handler;
    /**
     * 副主任类, 可以批准3天以内的假期申请
     */
    public class ViceManager extends LeaveHandler 
    {
        @Override
        public void processLeave(int days) 
        {
            if(days<=3)
            {
                System.out.println(this.getClass().getName()+"批准了"+days+"天假");
            }
            else
            {
                successor.processLeave(days);
            }
        }
    }


    package com.pattern.handler;
    /**
     * 主任类, 可以批准5天以内的假期申请
     */
    public class Manager extends LeaveHandler {
        @Override
        public void processLeave(int days) 
        {
            if(days<=5)
            {
                System.out.println(this.getClass().getName()+"批准了"+days+"天假");
            }
            else
            {
                successor.processLeave(days);
            }
        }
    }


    package com.pattern.handler;
    /**
     * 总经理类,可以批准10天以内的假期申请
     * 假期超过10天, 就拒绝申请
     */
    public class GeneralManager extends LeaveHandler {
        @Override
        public void processLeave(int days) 
        {
            if(days<=10)
            {
                System.out.println(this.getClass().getName()+"批准了"+days+"天假");
            }
            else
            {
                System.out.println(this.getClass().getName()+"不批准"+days+"天假");
            }
        }
    }


    package com.pattern.handler;
    public class LeaveHandlerFactory {
        /**
         * 创建LeaveHandler的工厂方法
         */
        public static LeaveHandler createPriceHandler() 
        {
            LeaveHandler gl = new GroupLeader();
            LeaveHandler vm = new ViceManager();
            LeaveHandler m = new Manager();
            LeaveHandler gm = new GeneralManager();

            gl.setSuccessor(vm);
            vm.setSuccessor(m);
            m.setSuccessor(gm);

            return gl;
        }
    }


    package com.pattern;
    import java.util.Random;
    import com.pattern.handler.LeaveHandler;
    import com.pattern.handler.LeaveHandlerFactory;
    /**
     * 工作人员,申请假期
     */
    public class Client {
        private LeaveHandler leaveHandler;
        public void setLeaveHandler(LeaveHandler leaveHandler) 
        {
            this.LeaveHandler = leaveHandler;
        }
        public void requestLeave(int days)
        {
            leaveHandler.processLeave(days);
        }
        public static void main(String[] args)
        {
            Client client = new Client();  
            client.setLeaveHandler(LeaveHandlerFactory.
            createLeaveHandler());
            Random random = new Random();
            for(int i=1;i<=100;i++){
                System.out.print(i+":");
                client.requestLeave(random.nextInt(20));
            }   
        }
    }
    代码重点分析:
    ①抽象类LeaveHandler包含一个自身类型的数据域,这个数据域的别名叫做责任链上的后继者,当本类的对象无权处理请求时,就将该请求传递 
给该数据域对应的对象进行处理,这一点非常重要,是形成责任链的关键所在!
    ②抽象类LeaveHandler属于Java中泛指的接口,这里使用抽象类作为接口,体现了面向接口编程的思想,这一点要注意!
    ③这里将不同类型的处理者的产生交由工厂类LeaveHandlerFactory来完成,体现了面向对象(OO)中类设计的单一职责原则,即对于某一 
接口或类,只把该接口或类的相关方法放进该接口或类中。同时,Java的命名规范要求我们设计类或接口时,能够见名知意,每一个类的类名必须 
代表着该类的语义!
    ④通过分析上述代码,可以发现职员类只和import com.pattern.handler.LeaveHandler以及import com.pattern.handler.LeaveHandlerFactory两个类相关联, 
并没有和继承于抽象类LeaveHandler的具体类相关联,这就带来了业务变更时, 
无需修改接口,只需要增加继承于LeaveHandler的类即可;比如,当公司中等级变化时(对应管理人员的等级有所增加),可以通过再设计一个 
对应类,并在工厂类中进行该类对象的获取,并将其嵌入责任链中,即可实现该项目仍可以正常工作,这就体现了设计模式应对不同场景时独具 
的优势,体现了项目的可扩展性!
    在责任链模式中存在着一些缺点,就本例来说:
    ①当请假的天数较少,只需要经过一个或者少数的处理者就可以处理该请求,那么这就造成之后的处理者被创建出来,但是并没有参与业务 
处理,造成时间和空间上的浪费。
    ②当多个职员请假时,需要分别创建一组管理人员对象,这就造成了不必要的开销,其实,只需一组管理人员对象即可处理多名职员的请假请求。
    责任链模式在Java的前端或者后台开发中也会常常遇到,比如后端开发中遇到的异常处理机制、Java Web中的过滤器链;
前端开发中的JavaScript中的事件触发处理过程,都蕴含了责任链模式的设计思想!

猜你喜欢

转载自blog.csdn.net/boker_han/article/details/78357659