模板方法模式
概述
定义一个操作中的算法骨架,而将一些步骤延迟到之类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
这里的“算法”,我们可以理解为广义上的“业务逻辑”
其核心是为了复用
结构图
代码实现
通过继承的方式
模板方法
/// <summary> /// 模板方法抽象 /// </summary> public abstract class AbstractClass { public abstract void PrimitiveOperation1(); public abstract void PrimitiveOperation2(); public void TemplateMethod() { PrimitiveOperation1(); PrimitiveOperation2(); Console.WriteLine(""); } }
/// <summary> /// 模板方法实现A /// </summary> public class ConcreteClassA : AbstractClass { public override void PrimitiveOperation1() { Console.WriteLine("具体类A方法1实现"); } public override void PrimitiveOperation2() { Console.WriteLine("具体类A方法2实现"); } }
/// <summary> /// 模板方法实现B /// </summary> public class ConcreteClassB : AbstractClass { public override void PrimitiveOperation1() { Console.WriteLine("具体类B方法1实现"); } public override void PrimitiveOperation2() { Console.WriteLine("具体类B方法2实现"); } }
客户端
class Program { static void Main(string[] args) { AbstractClass c; c = new ConcreteClassA(); c.TemplateMethod(); c = new ConcreteClassB(); c.TemplateMethod(); Console.Read(); } }
运行结果
通过委托回调的方式
模板类
public class CallBackTemplateClass { public void TemplateMethod(Func<string, string> callback) { string str = "123"; str = callback(str); str = str + str; Console.WriteLine(str); } }
客户端
static void Main(string[] args) { CallBackTemplateClass callBackTemplateClass = new CallBackTemplateClass(); callBackTemplateClass.TemplateMethod((string str) => { return str + "000"; }); Console.Read(); }
运行结果
类组合的方式实现
像 C#这种只支持单继承的语言,基于模板模式编写的子类,已经继承了一个父类,不再具有继承的能力。
如果某个类中定义了多个模板方法,每个方法都有对应的抽象方法,那即便我们只用到其中的一个模板方法,子类也必须实现所有的抽象方法。而回调就更加灵活,我们只需要往用到的模板方法中注入回调对象即可。
模板类
/// <summary> /// 类组合的方式实现 /// </summary> public class CompositionTemplateClass { ICompositionTemplate compositionTemplate; public CompositionTemplateClass(ICompositionTemplate compositionTemplate) { this.compositionTemplate = compositionTemplate; } public void TemplateMethod() { compositionTemplate.PrimitiveOperation1(); compositionTemplate.PrimitiveOperation2(); } }
抽象算法类
public interface ICompositionTemplate { public void PrimitiveOperation1(); public void PrimitiveOperation2(); }
算法实现
public class CompositionTemplateA : ICompositionTemplate { public void PrimitiveOperation1() { Console.WriteLine("具体实现1"); } public void PrimitiveOperation2() { Console.WriteLine("具体实现2"); } }
客户端
static void Main(string[] args) { CompositionTemplateA compositionTemplateA = new CompositionTemplateA(); CompositionTemplateClass compositionTemplateClass = new CompositionTemplateClass(compositionTemplateA); compositionTemplateClass.TemplateMethod(); Console.Read(); }
运行结果
优势
封装不变部分,扩展可变部分。
提取公共代码,便于维护。
行为由父类控制,子类实现。
子类还可以提供扩展点实现模板类,让子孙类可以不直接重写模板方法中的方法,这样还可以做封装
使用场景
知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关。
有多个子类共有的方法,且逻辑相同。
重要的、复杂的方法,可以考虑作为模板方法。
缺陷
对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统实现的复杂度。
由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。