首页 > 代码库 > 设计模式 之 职责链

设计模式 之 职责链

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


请假条件:


1.专业课第一
    如果专业课和提高班的课程冲突(包括考试),可以直接和各期纪委负责人请假。(每天上课,由纪委负责人查考勤)
2.百善孝为先
    父母生病、亲属故亡需要回家,可以向米老师请假,并告知纪委;如果非父母生病,需要照顾、料理,超过10天,可以向米老师请假,并告知纪委。
3.身体是革命本钱
    自己生病可以请假,半天之内可以由各期纪委负责人批准,超过半天应该向老师请假,并告知纪委。
4.急事请假
    在规定范围内(三小时之内),直接跟各期纪委负责人请假;三小时以上或规定范围外,需要跟老师请假,之后再和各期纪委负责人打招呼。其他,由纪委负责人决定,如果纪委负责人不能决定的,交于老师决定。


以上是我们提高班的请假条例,有了这个条例,我们就知道如果有一天我们需要请假,有没有满足请假条件,该向谁请假!下面让我们看看代码实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Chain_of_Responsibility
{
    class Program
    {
        //学生接口
        public interface IStudent{
            //获得学生请假级别:级别0:3小时内(纪委直接处理),级别1:超过3小时(由老师处理)
            int getLevel();
            //获得学生请假消息
            string getRequestMessage();
        }
        //学生实现类
        public class Student :IStudent {
            //请假级别
            private int level=-1;
            //请假消息
            private string message;

            public Student(int level, String message)
            {
                this.level = level;
                this.message=message;
            }

            public int getLevel()
            {
                return this.level;
            }

            public string getRequestMessage(){
                return this.message;
            }
        }
        //抽象处理者接口
        public interface IHandler
        {
            //处理请求
            void handleRequest(IStudent student);

            //设置下一个处理着
            void setHandler(IHandler handler);

        }
        //抽象处理者
        public abstract class AbstractHandler : IHandler
        {
            //下一个处理者
            private IHandler handler;

            //请假级别
            private int level = -1;

            //设置级别
            public AbstractHandler(int level)
            {
                this.level = level;
            }
            //处理请求,交由子类负责进行具体的处理
            public abstract void process(IStudent student);

            public void handleRequest(IStudent student)
            {
                if (student != null)
                {
                    if (this.level == student.getLevel())
                    {
                        //如果请假级别和当前级别一致,则当前对象进行处理
                        this.process(student);
                    }
                    else
                    {
                        if (this.handler != null)
                        {
                            Console.WriteLine(student.getRequestMessage() + " 请求米老师处理!");
                            //如果当前对象处理不了,则交给下一个处理者进行处理
                            this.handler.handleRequest(student);
                        }
                    }
                }
            }
            //设置下一个处理者
            public void setHandler(IHandler handler)
            {
                this.handler = handler;
            }
        }

        //纪委
        public class DisciplineHandler : AbstractHandler
        {
            public DisciplineHandler():base(0){}

            public override  void process(IStudent student)
            {
                Console.WriteLine("纪委 批复:" + student.getRequestMessage ());
            }
          
        }
        //老师
        public class TeacherHandler : AbstractHandler
        {
            public TeacherHandler() : base(1) { }

            public override  void process(IStudent student)
            {
                Console.WriteLine("老师 批复:" + student.getRequestMessage());
            }
        }

        //设置职责链关联
        public class ProcessHandler
        {
            private IHandler disciplineHandler;
            private IHandler teacherHandler;

            //单例模式
            private static ProcessHandler processHandler = new ProcessHandler();

            private ProcessHandler()
            {
                this.disciplineHandler = new DisciplineHandler();
                this.teacherHandler = new TeacherHandler();

                this.disciplineHandler.setHandler(this.teacherHandler);
            }

            public static ProcessHandler getInstance()
            {
                return processHandler;
            }

            //发送请假请求
            public void sendMessage(IStudent student)
            {
                this.disciplineHandler.handleRequest(student);
            }
        }

        static void Main(string[] args)
        {
            ProcessHandler processHandler = ProcessHandler.getInstance();

            IStudent student0 = new Student(0, "学生张XX快递到了,要请假20分钟!");
            IStudent student1 = new Student(1, "学生李XX运动时摔伤了腿,要请假一周!");
            Console.WriteLine("************************************************************");
            processHandler.sendMessage(student0);
            Console.WriteLine("************************************************************");
            processHandler.sendMessage(student1);
            Console.WriteLine("************************************************************");
        }
    }
}





类图:

          



职责链模式包含如下几个角色:
    Handler(抽象处理者):定义一个处理请求的接口。一般设计为抽象类,如果需要,抽象类可以定义出一个方法,以设定和返回下家的引用,通过该引用,处理者可以连成一条链。
    ConcreteHandler(具体处理者):具体处理者接收到请求后,可以选择将请求处理掉,或者将请求传给下家。由于处理者持有下家引用,因此,如果需要,具体处理者可以访问下家。


主要优点:
    1.一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,降低了系统的耦合度。
    2.请求处理对象仅需维持一个指向其后继者的引用,可简化对象的相互连接。
    3.在给对象分派职责时,职责链可以给我们更多的灵活性。


      
主要缺点:
    1.一个请求也可能因职责链没有被正确配置而得不到处理。
    2.对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响。


 
适用场景:
    1.有多个对象处理同一个请求,具体由哪一个来处理还不确定,只有在运行时才能确定哪个对象处理的情况。
    2.消息具有多个接收者,而接收对象又是不明确的情况。只需要向其中的一个对象发出消息,由其内部具体处理。
    3.同一个消息的多个处理对象可能会动态增加或者减少,需要动态地指定的情况。




相关模式:
    1.外观:在设置职责链时,可能会用到外观,让客户端只与外观打交道。
    2.命令:设计了请求传递的行为,请求的传递就用到了命令模式。
    3.观察者:事件触发,将消息发送出去,信息接收者可以同时存在多个。
    4.职责链时按照既定规则进行一系列的消息处理,并且只有一个接收者接收消息进行传递。




设计模式 之 职责链