介绍
模板方法(TemplateMethod):行为型模式。定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.
代码结构图
角色
AbstractClass:是抽象类,其实也就是一抽象模板,定义并实现了一个模板的方法,这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法
abstract class AbstractClass
{
public abstract void PrimitiveOperation1(); //一些抽象行为,放到子类去实现
public abstract void PrimitiveOperation2();
public void TemplateMethod()//模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,它们都推迟到子类实现
{
PrimitiveOperation1();
PrimitiveOperation2();
Console.WriteLine("");
}
}
ConcreteClass(具体子类):实现父类所定义的一个或多个抽象方法。每一个AbstractClass都可以有任意多个ConcreteClass都可以与之对应,而每一个ConcreteClass都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
class ConcreteClassA : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("具体类A方法1实现"); //与ConcreteClassB不同的方法实现
}
public override void PrimitiveOperation2()
{
Console.WriteLine("具体类B方法2实现");
}
}
class ConcreteClassB : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("具体类B方法1实现"); //与ConcreteClassA不同的方法实现
}
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.ReadLine();
}
以大话设计模式中的例子为例
代码结构图
客户端代码
static void Main(string[] args)
{
Console.WriteLine("学生甲抄的试卷: ");
TestPaper studentA = new TestPaperA();
studentA.TestQuestion1();
studentA.TestQuestion2();
studentA.TestQuestion3();
Console.WriteLine("学生乙抄的试卷: ");
TestPaper studentB = new TestPaperB();
studentB.TestQuestion1();
studentB.TestQuestion2();
studentB.TestQuestion3();
Console.ReadLine();
}
试卷的代码
class TestPaper
{
public void TestQuestion1()
{
Console.WriteLine("杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
}
public void TestQuestion2()
{
Console.WriteLine("杨过、程英、陆无双铲除情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区的沙漠化");
}
public void TestQuestion3()
{
Console.WriteLine("蓝凤凰致使华山师徒、桃花谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的牛奶 e.以上全不对");
}
}
三道问题的代码
public void TestQuestion1()
{
Console.WriteLine("杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
Console.WriteLine("答案:"+Answer1());
}//问题1
protected virtual string Answer1()
{
return "";
}//问题1答案
public void TestQuestion2()
{
Console.WriteLine("杨过、程英、陆无双铲除情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区的沙漠化");
Console.WriteLine("答案:" + Answer2());
}//问题2
protected virtual string Answer2()
{
return "";
}//问题2答案
public void TestQuestion3()
{
Console.WriteLine("蓝凤凰致使华山师徒、桃花谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的牛奶 e.以上全不对");
Console.WriteLine("答案:" + Answer3());
}//问题3
protected virtual string Answer3()
{
return "";
}//问题3答案
学生甲的试卷继承TestPaper。并有答案
class TestPaperA : TestPaper
{
public new void TestQuestion1()
{
base.TestQuestion1();
Console.WriteLine("答案:b");
}
public new void TestQuestion2()
{
base.TestQuestion2();
Console.WriteLine("答案b");
}
public new void TestQuestion3()
{
base.TestQuestion3();
Console.WriteLine("答案:b");
}
}
学生乙的试卷继承TestPaper。并有答案
class TestPaperB : TestPaper
{
public new void TestQuestion1()
{
base.TestQuestion1();
Console.WriteLine("答案:b");
}
public new void TestQuestion2()
{
base.TestQuestion2();
Console.WriteLine("答案:b");
}
public new void TestQuestion3()
{
base.TestQuestion3();
Console.WriteLine("答案:b");
}
}
优点
1)模板方法模式在一个类中形式化地定义算法,而由它的子类实现细节的处理。
2)模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。
3)模板方法模式导致一种反向的控制结构,这种结构有时被称为“好莱坞法则” ,即“别找我们,,我们找你”通过一个父类调用其子类的操作(而不是相反的子类调用父类),通过对子类的扩展增加新的行为,符合“开闭原则”
2)模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。
3)模板方法模式导致一种反向的控制结构,这种结构有时被称为“好莱坞法则” ,即“别找我们,,我们找你”通过一个父类调用其子类的操作(而不是相反的子类调用父类),通过对子类的扩展增加新的行为,符合“开闭原则”
缺点
每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,但是更加符合“单一职责原则”,使得类的内聚性得以提高。