一个真实的故事
大学的时候就开过一门课程,讲设计模式,可是大学生没什么编程实践经验,在大学里面听设计模式的感觉,就像听天书。听着都有道理,可是完全领会不到其中的奥妙,大抵原因就在于没有走过弯路,没有吃过设计不当的亏。古人云,“操千曲而后晓声,观千剑而后识器”,诚不欺我。
博主在之前的某个项目中,设计出了一些工具类,像属性窗口,错误提示窗口,还有一个窗口管理类管理它们,当时我实现工具保存时候的代码是这样的:
class WindowManager { private List<ITool> _Tools = new List<ITool>(); public void AddTool(ITool tool) { _Tools.Add(tool); } public void SaveAllTools() { foreach(var tool in _Tools) { tool.Save(); } } } interface ITool { bool BeforeSave(); void Save(); void AfterSave(); } class PropertyWindow : ITool { public bool BeforeSave() { //do something specific here return true; } public void Save() { if (BeforeSave()) { //do save AfterSave(); } } public void AfterSave() { } } class ErrorLis : ITool { public bool BeforeSave() { //do something specific here return true; } public void Save() { if (BeforeSave()) { //do save AfterSave(); } } public void AfterSave() { } }
当时博主对这段代码还挺满意,完全没有看出这儿有什么问题,觉得这简直写的太OO了,有类,有接口,有针对接口编程,至于新加的工具类,也不会影响原来的代码,简直太符合开闭原则了。老铁,没毛病!
好日子就这么继续下去,每当需要新添加一个工具,我就新加一个类,在类里面实现Save的逻辑,直到有一天,添加了一个ResourceControl
class ResourceControl : ITool { public bool BeforeSave() { //do something specific here return true; } public void Save() { if (!BeforeSave()) { //do save AfterSave(); } } public void AfterSave() { } }
在它的save里面,我把if(BeforeSave())写成了if(!BeforeSave())。。。
于是,我又额外花了一些时间来找到这个问题,修改它并在下次添加新类的时候战战兢兢提醒自己不要犯这种低级的错误。那么,我们有没有好的办法来解决这个问题呢?
问题分析
其实就算每次添加新类的时候我们都能仔细的小心避免维护相同的逻辑,这段代码的设计也还是有可以改进的地方,比如,BeforeSave和AfterSave在这里作为接口ITool的一部分而公开,意味着客户代码可以自由的调用BeforeSave和AfterSave,然而这很可能并不是代码作者的本意,毕竟,不调用Save而单独调用BeforeSave和AfterSave有什么意义呢?让客户能够看到更多不必要的方法,增加了客户错误使用接口的可能性,不是么?
综上所述,我们需要解决的问题如下:
- 抽象出Save, BeforeSave和AfterSave的逻辑关系,在一个地方固定下来,确保新增加的类所实现的这三个方法,都能自动具有这种逻辑关系。
- 对客户代码隐藏不必要的接口。
这种场景下面,我们需要用到设计模式中的TemplateMethod(模版方法)模式。
TemplateMethod模式
在WIKI上面,TemplateMethod模式的定义如下,
In software engineering, the template method pattern is a behavioral design pattern that defines the program skeleton of an algorithm in an operation, deferring some steps to subclas
本文来源gao!%daima.com搞$代*!码$网3
ses. It lets one redefine certain steps of an algorithm without changing the algorithm’s structure.