设计模式之责任链模式

责任链模式,Chain ofResponsibility,就是说有一系列的处理过程,这些处理过程有先后顺序,就跟ASP.NET FrameworkPipeline事件一样,挨个对request进行处理。

 

下面我们用一个简单的例子来说说这种设计模式。我们假设一种场景,有一条message(字符串)要从A传送到B,但是这个过程中会有多个处理过程,比如说过滤掉敏感字符("government"),并且把"haha"替换成笑脸"-^^-".

 

1.我们可以设定一个IFilter接口,然后让所有的处理过程都实现这个接口。然后我们设置一个Filter的集合,把所有的Filter都放到这个集合里边来。

class Program
    {
        static void Main(string[] args)
        {
            Message message = new Message()
            {
                ID = 1,
                Content = "Our government is good. haha"
            };

            FilterChain chain = new FilterChain();
            chain.AddFilter(new SensitiveWordsFilter());
            chain.AddFilter(new EmotionFaceFilter());

            chain.doFilter(message);

            Console.WriteLine(message.Content);
            Console.ReadLine();
        }
    }


    public class Message
    {
        public int ID { get; set; }

        public String Content { get; set; }
    }

    public interface IFilter
    {
        void doFilter(Message message);
    }

    public class SensitiveWordsFilter : IFilter
    {
        public void doFilter(Message message)
        {
            message.Content = message.Content.Replace("government", "***");
        }
    }

    public class EmotionFaceFilter : IFilter
    {
        public void doFilter(Message message)
        {
            message.Content = message.Content.Replace("haha", "-^^-");
        }
    }

    public class FilterChain
    {
        private readonly IList<IFilter> list;

        public void AddFilter(IFilter filter)
        {
            this.list.Add(filter);
        }

        public FilterChain()
        {
            this.list = new List<IFilter>();
        }

        public void doFilter(Message message)
        {
            foreach (var filter in list)
            {
                filter.doFilter(message);
            }
        }

    }

这段代码的运行结果如下图所示,一切按计划进行。



2.此时,我们的需求不仅仅局限在往一个Chain集合中加入Filter,现在我们需要向一个Chain集合中加入另一个Chain集合。这时候我们怎么办?我们可以让FilterChain也实现IFitler接口,那么我们就可以直接调用FilterChainAdd方法了。

class Program
    {
        static void Main(string[] args)
        {
            Message message = new Message()
            {
                ID = 1,
                Content = "Our government is good. haha  five"
            };

            FilterChain chain = new FilterChain();
            chain.AddFilter(new SensitiveWordsFilter());
            chain.AddFilter(new EmotionFaceFilter());

            FilterChain chain2 = new FilterChain();
            chain2.AddFilter(new NumberFilter());

            chain.AddFilter(chain2);
            chain.doFilter(message);

            Console.WriteLine(message.Content);
            Console.ReadLine();
        }
    }


    public class Message
    {
        public int ID { get; set; }

        public String Content { get; set; }
    }

    public interface IFilter
    {
        void doFilter(Message message);
    }

    public class SensitiveWordsFilter : IFilter
    {
        public void doFilter(Message message)
        {
            message.Content = message.Content.Replace("government", "***");
        }
    }

    public class EmotionFaceFilter : IFilter
    {
        public void doFilter(Message message)
        {
            message.Content = message.Content.Replace("haha", "-^^-");
        }
    }

    public class NumberFilter : IFilter
    {
        public void doFilter(Message message)
        {
            message.Content = message.Content.Replace("five", "5");
        }
    }

    public class FilterChain : IFilter
    {
        private readonly IList<IFilter> list;

        public void AddFilter(IFilter filter)
        {
            this.list.Add(filter);
        }

        public FilterChain()
        {
            this.list = new List<IFilter>();
        }

        public void doFilter(Message message)
        {
            foreach (var filter in list)
            {
                filter.doFilter(message);
            }
        }

    }

运行结果如下图所示。



对于第2种方式总结一下,就是如何能够让一个责任链加入到另一个责任链中。当然我们可以依次遍历这个责任链集合,然后一个个的加到另外的责任链中。但这种方法很繁琐。最简单方法是这样做,我们让FilterChain也实现IFilter接口,把它看成一个大个的Filter,然后FilterChain中进行处理的方法要与NumberFilter,SensitiveWordsFilter等这些具体的Filter中的方法同名,并且都是实现IFilter接口中的方法。

 

另外,还有一种链式编程的技巧。在FilterChain中,我们让每次AddFilter之后,都让其返回自身。这样我们所以的Add方法都能在一行代码中完成。

	public FilterChain AddFilter(IFilter filter)
        {
            this.list.Add(filter);
            return this;
        }

在使用的时候,就可以这样。

FilterChain chain = new FilterChain();chain.AddFilter(new SensitiveWordsFilter()).AddFilter(new EmotionFaceFilter());

3.现在我们的需求又变了。我们希望我们的责任链处理器能向ASP.NET Pipeline那样,去的时候按先后顺序处理Request,回来的时候按照顺序处理Repsone.

class Program
    {
        static void Main(string[] args)
        {
            Request request = new Request()
            {
                ID = 1,
                Content = "This is the orginal request string. "
            };

            Response response = new Response()
            {
                ID = 1,
                Content = "This is the orginal response string. "
            };

            FilterChain chain = new FilterChain();
            chain.AddFilter(new SensitiveWordsFilter())
                .AddFilter(new EmotionFaceFilter());

            FilterChain chain2 = new FilterChain();
            chain2.AddFilter(new NumberFilter());

            chain.AddFilter(chain2);
            chain.doFilter(request, response);

            Console.WriteLine(request.Content);
            Console.WriteLine();
            Console.WriteLine(response.Content);
            Console.ReadLine();
        }
    }


    public class Request
    {
        public int ID { get; set; }

        public String Content { get; set; }
    }

    public class Response
    {
        public int ID { get; set; }

        public String Content { get; set; }
    }

    public interface IFilter
    {
        void doFilter(Request request, Response response);
    }

    public class SensitiveWordsFilter : IFilter
    {
        public void doFilter(Request request, Response response)
        {
            request.Content = request.Content + " --SensitiveFilter In-- ";
            response.Content = response.Content + " --SensitiveFilter Out-- ";
        }
    }

    public class EmotionFaceFilter : IFilter
    {
        public void doFilter(Request request, Response response)
        {
            request.Content = request.Content + " --EmotionFaceFilter In-- ";
            response.Content = response.Content + " --EmotionFaceFilter Out-- ";
        }
    }

    public class NumberFilter : IFilter
    {
        public void doFilter(Request request, Response response)
        {
            request.Content = request.Content + " --NumberFilter In-- ";
            response.Content = response.Content + " --NumberFilter Out-- ";
        }
    }

    public class FilterChain : IFilter
    {
        private readonly IList<IFilter> list;

        public FilterChain AddFilter(IFilter filter)
        {
            this.list.Add(filter);
            return this;
        }

        public FilterChain()
        {
            this.list = new List<IFilter>();
        }

        public void doFilter(Request request, Response response)
        {
            foreach (var filter in list)
            {
                filter.doFilter(request, response);
            }
        }

    }

运行结果如下图所示。




但是这不太符合要求。因为进去的时候SensitiveFilter是第一个进行处理的,那么response出来的时候,这个应该是最后一个进行处理才对。

 

我们可以在FilterChain集合中设置一个变量index,然后一层层的调用。具体代码如下。

internal class Program
    {
        private static void Main(string[] args)
        {
            Request request = new Request()
            {
                ID = 1,
                Content = "This is the orginal request string. "
            };

            Response response = new Response()
            {
                ID = 1,
                Content = "This is the orginal response string. "
            };

            FilterChain chain = new FilterChain();
            chain.AddFilter(new SensitiveWordsFilter())
                .AddFilter(new EmotionFaceFilter());

            FilterChain chain2 = new FilterChain();
            chain2.AddFilter(new NumberFilter());

            chain.AddFilter(chain2);
            chain.doFilter(request, response, chain);

            Console.WriteLine(request.Content);
            Console.WriteLine();
            Console.WriteLine(response.Content);
            Console.ReadLine();
        }
    }


    public class Request
    {
        public int ID { get; set; }

        public String Content { get; set; }
    }

    public class Response
    {
        public int ID { get; set; }

        public String Content { get; set; }
    }

    public interface IFilter
    {
        void doFilter(Request request, Response response, FilterChain chain);
    }

    public class SensitiveWordsFilter : IFilter
    {
        public void doFilter(Request request, Response response, FilterChain chain)
        {
            request.Content = request.Content + " --SensitiveFilter In-- ";
            chain.doFilter(request, response, chain);
            response.Content = response.Content + " --SensitiveFilter Out-- ";
        }
    }

    public class EmotionFaceFilter : IFilter
    {
        public void doFilter(Request request, Response response, FilterChain chain)
        {
            request.Content = request.Content + " --EmotionFaceFilter In-- ";
            chain.doFilter(request, response, chain);
            response.Content = response.Content + " --EmotionFaceFilter Out-- ";
        }
    }

    public class NumberFilter : IFilter
    {
        public void doFilter(Request request, Response response, FilterChain chain)
        {
            request.Content = request.Content + " --NumberFilter In-- ";
            chain.doFilter(request, response, chain);
            response.Content = response.Content + " --NumberFilter Out-- ";
        }
    }

    public class FilterChain : IFilter
    {
        private readonly IList<IFilter> list;
        private int index = 0;

        public FilterChain AddFilter(IFilter filter)
        {
            this.list.Add(filter);
            return this;
        }

        public FilterChain()
        {
            this.list = new List<IFilter>();
        }

        public void doFilter(Request request, Response response, FilterChain chain)
        {
            if (index == list.Count)
            {
                return;
            }
            IFilter filter = list[index];
            index++;
            filter.doFilter(request, response, chain);
        }
    }

运行结果如图。符合最终的要求。



综合来讲,责任链模式,就是对于同一个对象进行有序的先后处理的一些工具类的集合。本文文字比较简单,但是代码很详细,希望大家能够从分析代码中有些收获。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值