有人说,如果只学习一种设计模式,那么就学模板方法模式好了。有些夸张却由此可见模板方法模式的地位。
它是这样定义的:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
我的理解是,当我们知道一个算法所需要的关键步骤,并确定了它们的执行顺序,但不知道某些具体步骤或者某些步骤的实现与具体环境相关时,就可以这么做:把我们不知道具体实现的步骤封装成抽象方法,提供一个按正确顺序调用它们的具体方法,这个方法就是TemplateMethod,它是一个抽象基类,子类通过继承抽象基类去实现某些步骤的抽象方法,而工作流程总由父类控制的。因此,使用模板方法模式要考虑提炼代码,将重复的、类似的代码都上升到父类中去,成为公共的部分即子类的模板而让子类去继承父类,子类在实现的时候,只在某个更详细的步骤上与其他子类不同,重写父类的虚方法。相同的方法在不同的子类中具有不同的实现方式就利用了多态性,从而实现了代码的复用。
模板方法模式的类型:
行为型模式(还有命令模式、观察者模式、策略模式、职责模式、中介者模式、解释器模式)
模板方法模式结构图:
根据结构图写出代码:
//AbstractClass是抽象类,定义并实现了一个模板方法 abstract class AbstractClass { public abstract void PrimitiveOperation1();//一些抽象行为,放到子类去实现 public abstract void PrimitiveOperation2(); public void TemplateMethod()//模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,它们都推迟到子类实现 { PrimitiveOperation1(); PrimitiveOperation2(); Console.WriteLine(""); } } //ConcreteClass实现父类所定义的一个或多个抽象方法 class ConcreteClassA : AbstractClass { public override void PrimitiveOperation1() { Console.WriteLine("具体类A方法1实现"); } public override void PrimitiveOperation2() { Console.WriteLine("具体类A方法2实现"); } } class ConcreteClassB : AbstractClass { public override void PrimitiveOperation1() { Console.WriteLine("具体类B方法1实现"); } public override void PrimitiveOperation2() { Console.WriteLine("具体类B方法2实现"); } }
static void Main(string[] args) { AbstractClass c; c = new ConcreteClassA(); c.TemplateMethod(); c = new ConcreteClassB(); c.TemplateMethod(); Console.Read(); }
好处:
模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势,提供了一个很好的代码复用平台。当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为会重复出现。我们通过模板方法模式把这些行为拿出来,这样就使得子类摆脱重复的不变行为的纠缠,利用抽象和封装做到了解耦合。
模板方法模式与前几个模式的联系:
模板方法模式由抽象父类控制顶级逻辑,并把基本操作的实现推迟到子类去实现,这是通过继承的手段来达到对象的复用,可以说这完全满足在不被修改的情况下被扩展,即符合开放-封闭原则。
模板中的虚方法实际上是使用了工厂方法模式,将父类的执行逻辑延迟到子类。有时候模板方法中定义算法的步骤会用到策略模式,因为有时这个算法不止一种,那么我们就可以用策略模式封装几套算法。
学后感:
学过一些设计模式后,我才真正领会到编程是一种非常有逻辑性的活动,这完全不像是之前在VB中学到的顺序式的写代码。越来越多的结构与层次的融合让我对编程充满了好奇与期待。