C#责任链设计模式,责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任,废话不多说,下面是应用责任链设计模式通过扩展名获取文件类型的demo。
public enum FileTypeEnum { UnKnow=0, PDF=1, Doc=2, PPT=3, Img=4 } public abstract class FileTypeHandler { private FileTypeHandler nextHandler; protected abstract string ExtNames { get; } protected abstract FileTypeEnum FileTypeEnum { get; } public FileTypeHandler SetNextHandler(FileTypeHandler fileTypeHandler) { nextHandler = fileTypeHandler; return fileTypeHandler; } public virtual FileTypeEnum Process(string extName) { if(nextHandler!=null) { return nextHandler.Process(extName); } else { return FileTypeEnum.UnKnow; } } protected FileTypeEnum ProcessHandler(string extName) { if (Array.IndexOf(ExtNames.Split(','), extName) > -1) { return FileTypeEnum; } return FileTypeEnum.UnKnow; } } public class ImgFileHandler:FileTypeHandler { protected override string ExtNames => ".jpg,.jpeg,.png,.bmp"; protected override FileTypeEnum FileTypeEnum => FileTypeEnum.Img; public override FileTypeEnum Process(string extName) { if (ProcessHandler(extName) == FileTypeEnum.UnKnow) { return base.Process(extName); } return FileTypeEnum; } } public class PdfFileHandler : FileTypeHandler { protected override string ExtNames => ".pdf"; protected override FileTypeEnum FileTypeEnum => FileTypeEnum.PDF; public override FileTypeEnum Process(string extName) { if (ProcessHandler(extName) == FileTypeEnum.UnKnow) { return base.Process(extName); } return FileTypeEnum; } } public class DocFileHandler : FileTypeHandler { protected override string ExtNames => ".doc,.docx"; protected override FileTypeEnum FileTypeEnum => FileTypeEnum.Doc; public override FileTypeEnum Process(string extName) { if (ProcessHandler(extName) == FileTypeEnum.UnKnow) { return base.Process(extName); } return FileTypeEnum; } } public class PPTFileHandler : FileTypeHandler { protected override string ExtNames => ".pptx"; protected override FileTypeEnum FileTypeEnum => FileTypeEnum.PPT; public override FileTypeEnum Process(string extName) { if (ProcessHandler(extName) == FileTypeEnum.UnKnow) { return base.Process(extName); } return FileTypeEnum; } }
上面定义了抽象类FileTypeHandler,ImgFileHandler、PdfFileHandler、DocFileHandler和PPTFileHandler分别为处理图片、PDF、Word和PPT类型的实现类,通过一个nextHandler链条指向下一个处理类,应用代码如下:
var fileExt = Path.GetExtension(DocUrl).ToLower();//要判断的文件扩展名 //责任链判断文件类型 ImgFileHandler img = new ImgFileHandler(); PdfFileHandler pdf = new PdfFileHandler(); DocFileHandler doc = new DocFileHandler(); PPTFileHandler ppt = new PPTFileHandler(); img.SetNextHandler(pdf).SetNextHandler(doc).SetNextHandler(ppt); return img.Process(fileExt);
在以下场景中可以考虑使用责任链模式:
- 一个系统的审批需要多个对象才能完成处理的情况下,例如请假系统等。
- 代码中存在多个if-else语句的情况下,此时可以考虑使用责任链模式来对代码进行重构。
责任链模式的优点不言而喻,主要有以下点:
- 降低了请求的发送者和接收者之间的耦合。
- 把多个条件判定分散到各个处理类中,使得代码更加清晰,责任更加明确。
责任链模式也具有一定的缺点,如:
- 在找到正确的处理对象之前,所有的条件判定都要执行一遍,当责任链过长时,可能会引起性能的问题
- 可能导致某个请求不被处理。
责任链降低了请求端和接收端之间的耦合,使多个对象都有机会处理某个请求。