模板方法模式(Template Method Pattern),定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
参与者
AbstractClass(抽象类)
— 定义抽象的原语操作(primitive operation),具体的子类将重定义它们以实现一个算法的各步骤。
— 实现一个模板方法 ,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。
ConcreteClass(具体类)
— 实现原语操作以完成算法中与特定子类相关的步骤。
模板方法导致一种反向的控制结构,这种结构有时被称为 “好莱坞法则”,即“别找我们,我们找你”。这 指的是一个父类调用一个子类的操作,而不是相反。
钩子操作(hook operations),它提供了缺省的行为,子类可以在必要时进行扩展。一个钩子操作在缺省操作通常是一个空操作。
参与者
AbstractClass(抽象类)
— 定义抽象的原语操作(primitive operation),具体的子类将重定义它们以实现一个算法的各步骤。
— 实现一个模板方法 ,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。
ConcreteClass(具体类)
— 实现原语操作以完成算法中与特定子类相关的步骤。
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyTemplateMethod
{
abstract class AbstractClass
{
public abstract void PrimitiveOperation1();
public abstract void PrimitiveOperation2();
public void ConcreteOperation()
{
Console.WriteLine("smile smile smile!");
}
public virtual void Hook() { }
// 模板方法,给出了逻辑的骨架
public void TemplateMethod()
{
PrimitiveOperation1();
PrimitiveOperation2();
ConcreteOperation();
Hook(); // 钩子
}
}
class ConcreteClassA : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("Left is what you can make it,");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("so try to make it beautiful!");
}
}
class ConcreteClassB : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("Things can only get better,");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("so all is well!");
}
public override void Hook()
{
Console.WriteLine("fighting!");
}
}
}
</span>
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyTemplateMethod
{
class Program
{
static void Main(string[] args)
{
AbstractClass c;
c = new ConcreteClassA();
c.TemplateMethod();
c = new ConcreteClassB();
c.TemplateMethod();
Console.ReadKey();
}
}
}
</span>
效果模板方法导致一种反向的控制结构,这种结构有时被称为 “好莱坞法则”,即“别找我们,我们找你”。这 指的是一个父类调用一个子类的操作,而不是相反。
钩子操作(hook operations),它提供了缺省的行为,子类可以在必要时进行扩展。一个钩子操作在缺省操作通常是一个空操作。
很重要的一点是模板方法应该指明哪些操作是钩子操作(可以被重定义)以及哪些是抽象操作(必须被重定义)。要有效地重用一个抽象类,子类编写者必须明确了解哪些操作是设计为有待重定义的。
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyTemplateMethod2
{
public abstract class CaffeineBeverage
{
public void prepareRecipe()
{
boilWater(); // 将水煮沸
brew();
pourInCup(); // 将饮料倒进杯子
if (customerWantsCondiments())
{
addCondiments();
}
}
public abstract void brew();
public abstract void addCondiments();
public void boilWater()
{
Console.WriteLine("Boiling water");
}
public void pourInCup()
{
Console.WriteLine("Pouring into cup");
}
public virtual bool customerWantsCondiments()
{
return true;
}
}
public class Tea : CaffeineBeverage
{
public override void brew()
{
Console.WriteLine("Steeping the tea");
}
public override void addCondiments()
{
Console.WriteLine("Adding Lemon");
}
}
public class CoffeeWithHook : CaffeineBeverage
{
public override void brew()
{
Console.WriteLine("Dripping coffee through filter");
}
public override void addCondiments()
{
Console.WriteLine("Adding Sugar and milk");
}
public override bool customerWantsCondiments()
{
string answer = getUserInput();
if (answer == "y")
{
return true;
}
else
{
return false;
}
}
private string getUserInput()
{
string answer;
Console.WriteLine("Would you like milk and sugar with you coffee?");
answer = Console.ReadLine();
return answer;
}
}
}
</span>
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyTemplateMethod2
{
class Program
{
static void Main(string[] args)
{
CaffeineBeverage cb = new Tea();
cb.prepareRecipe();
Console.WriteLine();
cb = new CoffeeWithHook();
cb.prepareRecipe();
Console.WriteLine();
CoffeeWithHook cw = new CoffeeWithHook();
cw.prepareRecipe();
Console.ReadKey();
}
}
}
</span>