北川广海の梦

北川广海の梦

设计模式:责任链与模版方法

2021-11-06

责任链模式

当我们面临一个流程性的处理的时候,例如我们需要构建一个请求的校验流程。
我们可能会写一个方法:ReqeuestCheck,然后在里面写下一大堆教研逻辑,if XXX,return XXX,else XXX return XXX。这样会使得方法大量膨胀,且难以维护。

而通常来说,这个校验的逻辑是可以分成不同的模块的,通过责任链模式,就可以优雅的解决这个问题。

class Program
    {
        static void Main(string[] args)
        {
            var handler1 = new HandlerA();
            var handler2 = new HandlerB();
            var handler3 = new HandlerC();
            handler1.SetNext(handler2);
            handler2.SetNext(handler3);
        }
    }

    public interface IHandler
    {
        void SetNext(IHandler handler);
        void Handle(params object[] request);
    }

    public class BaseHandler : IHandler
    {
        private IHandler _next;

        public void SetNext(IHandler handler)
        {
            _next = handler;
        }

        public virtual void Handle(params object[] request)
        {
            _next?.Handle(request);
        }
    }

    public class HandlerA : BaseHandler
    {
        public override void Handle(params object[] request)
        {
            throw new NotImplementedException();
        }
    }

    public class HandlerB : BaseHandler
    {
        public override void Handle(params object[] request)
        {
            throw new NotImplementedException();
        }
    }

    public class HandlerC : BaseHandler
    {
        public override void Handle(params object[] request)
        {
            throw new NotImplementedException();
        }
    }

通过构建这样的Handler,生成一条处理链路,这个链路就是责任链,责任链上的每一环,都只负责处理当前份内的事情,在下一阶段,就交给下一个处理器去完成。

模版方法

现在想象这样一个场景,我们需要从客户的文件中,进行数据分析。但是客户有三种不同的文件格式,分别是Word,Excel,以及PDF文件。我们可以分别写三个类实现三种文件的处理器,但是这样做会发现三个类之间有很多重复代码。而其实我们可以提取其中共同的方法为基类,然后在子类实现各自不同的逻辑。

public abstract class BaseAnalyzer
    {
        protected BaseAnalyzer()
        {
        }

        public abstract void OpenFile(string path);

        public abstract void ReadData();

        public virtual void AnalyzeData()
        {
            //some default thing
        }

        public virtual void GenerateReport()
        {
            //some default thing
        }
    }

    public class WordFileAnalyzer : BaseAnalyzer
    {
        public override void OpenFile(string path)
        {
        }

        public override void ReadData()
        {
        }
    }

    public class PdfFileAnalyzer : BaseAnalyzer
    {
        public override void OpenFile(string path)
        {
        }

        public override void ReadData()
        {
        }
    }

    public class ExcelFileAnalyzer : BaseAnalyzer
    {
        public override void OpenFile(string path)
        {
        }

        public override void ReadData()
        {
        }
    }

模版方法可以配合工厂模式,在不同的场景,使用不同的子类完成对应的处理。