综上所述,我们需要解决的问题如下:
抽象出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 subclasses. It lets one redefine certain steps of an algorithm without changing the algorithm's structure.
大概意思就是,模版方法模式是一种行为类设计模式,允许软件在更高的层次定义程序骨架,但是可以在子类推迟实现某些步骤。
类图如下:

这完全符合我们的需求,让我们试着修改我们的代码。
使用TemplateMethod重新实现的代码
class WindowManager
{
private List<AbstractTool> _Tools = new List<AbstractTool>();
public void AddTool(AbstractTool tool)
{
_Tools.Add(tool);
}
public void SaveAllTools()
{
foreach(var tool in _Tools)
{
tool.Save();
}
}
}
abstract class AbstractTool
{
protected abstract bool BeforeSave();
protected abstract void DoSave();
protected abstract void AfterSave();
public void Save()
{
if(!BeforeSave())
{
DoSave();
AfterSave();
}
}
}
class PropertyWindow : AbstractTool
{
protected override bool BeforeSave()
{
//do something specific here
return true;
}
protected override void DoSave()
{
}
protected override void AfterSave()
{
}
}
class ErrorLis : AbstractTool
{
protected override bool BeforeSave()
{
//do something specific here
return true;
}
protected override void DoSave()
{
}
protected override void AfterSave()
{
}
}
从上面我们可以看到,我们用一个抽象类AbstractTool代替之前的ITool接口,抽象类和接口的一个区别就是,抽象类可以在其中嵌入某些逻辑,所以我们在Save这个公共的非虚方法中,完全实现了我们的BeforeSave和AfterSave逻辑,仅仅留下了BeforeSave,AfterSave和DoSave给子类覆盖。这样我们得到的好处是:
抽象类只公开了一个Save方法,所以客户代码不用担心会调用其他错误的方法。 抽象类完全固定了Save逻辑,先调用BeforeSave检查,之后执行DoSave进行具体的Save事项,最后进行AfterSave行为。子类只需要重新依据子类的需求覆盖这三个虚方法即可。新添加的工具类,只要覆盖这三个虚方法,至于虚方法之间的逻辑,抽象类已经固定,不用担心。









