• 职责链模式


    1概述
        当一个请求,有多个处理对象时,如果硬编码指定某个由某个对象来处理,需要采用ifelse的结构,从而产生了代码的耦合,如果要添加新的请求处理对象或调整请求处理的次序,必然会修改同一个方法,违背开闭原则。

    2 GOF中的定义
    意图:  
    使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
    结构图:

    适用性:

    1>有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
    2>你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
    3>解耦ifelse,将处理对象组织一个链并希望处理的次序由客户端来定义;

    3项目中的例子
    在简单的审批处理中,经理与总经理有着不同的处理级别。比如,在请假审批中,经理可以批准3天的,而当要请假5天时需要总经理审批。在这里,我们定义请假3天的级别为3,请假5天的级别为5。
    4紧耦合的实现
    代码:

    View Code
        public class Manager
        {
            public void HandelRequest(int levelDays)
            {
                if (levelDays <= 3) 
                {
                    Console.WriteLine("经理处理请假");
                }
                else 
                {
                    Console.WriteLine("总经理处理请假");
                }
            }
        }
            static void Main(string[] args)
            {
                Manager manager = new Manager();
                manager.HandelRequest(4);
                Console.Read();
            }

    说明:在这里,不同的请求处理对象耦合在ifelse分支中,当新修改、添加新的请求处理对象,或要调整请求处理次序时,都要修改Manager的HandelRequest方法,很明显违背了开闭、单一职责原则。

    5松耦合的实现
    代码:

    View Code
        /// <summary>
        /// 处理请求对象的基类
        /// </summary>
        public abstract class Manager
        {
            /// <summary>
            /// 维护一个指向下一个请求处理对象的引用
            /// </summary>
            protected Manager nextHander;
    
            public void SetNextHander(Manager manager) 
            {
                this.nextHander = manager;
            }
    
            /// <summary>
            /// 请求处理方法,由子类实现
            /// </summary>
            /// <param name="reqLevel"></param>
            public abstract void HandelRequest(int reqLevel);
        }
    
        /// <summary>
        /// 经理
        /// </summary>
        public class NomalManager:Manager
        {
            public override void HandelRequest(int reqLevel)
            {
                if (reqLevel <= 3) 
                {
                    Console.WriteLine("{0}:同意请假", this.GetType().Name);
                }
                else if (nextHander != null)
                {
                    nextHander.HandelRequest(reqLevel);
                }
            }
        }
    
        /// <summary>
        /// 总经理
        /// </summary>
        public class GeneralManager:Manager
        {
            public override void HandelRequest(int reqLevel)
            {
                if (reqLevel > 3)
                {
                    Console.WriteLine("{0}:同意请假", this.GetType().Name);
                }
                else if (nextHander != null)
                {
                    nextHander.HandelRequest(reqLevel);
                }
            }
        }
    
            static void Main(string[] args)
            {
                Manager normalManager = new NomalManager();
                Manager generalManager = new GeneralManager();
                normalManager.SetNextHander(generalManager);
                normalManager.HandelRequest(3);
                normalManager.HandelRequest(4);
                Console.Read();
            }

    说明:在这里,将不同的请求处理行为抽象成类,然后将这些类构成一个链式结构(此时链的前后关系由客户端定义,提高了灵活性)。当有请求时,只需要调用处理链中的第一个就可以完成各种请求,不需要将某个请求与具体的处理对象关联了。

    6总结
    职责链模式解决的是将ifelse解耦,但它与策略模式不同,它将行为对象组织成一个链式结构来处理请求,一步步向后处理。很明显这样做会浪费一些性能,如加载了一些不会用的到类(因为只有一个对对象才会处理某个请求),另外如果请求只有最后一个才能处理,要经过之前的层层判断才会至最后一个。但是在一些业务系统中,这样的做会更加容易理解与维护。




  • 相关阅读:
    《那些年啊,那些事——一个程序员的奋斗史》——40
    《那些年啊,那些事——一个程序员的奋斗史》——41
    《那些年啊,那些事——一个程序员的奋斗史》——42
    《那些年啊,那些事——一个程序员的奋斗史》——40
    《那些年啊,那些事——一个程序员的奋斗史》——41
    《那些年啊,那些事——一个程序员的奋斗史》——42
    《那些年啊,那些事——一个程序员的奋斗史》——40
    箭牌卫浴(帮朋友发的广告贴)
    Playing with ptrace
    [open source]通过汉字得到拼音的函数库(getpinyin)发布
  • 原文地址:https://www.cnblogs.com/dataadapter/p/2653912.html
Copyright © 2020-2023  润新知