目录
模板方法模式
引言
定义
模板方法模式结构图
实例
实例描述
代码实现
模式分析
模板方法
基本方法
抽象方法
具体方法
钩子方法
总结
模式优点
模式缺点
在现实生活中很多事情的完成过程都包含几个基本步骤,例如到请客吃饭,无论吃什么,一般都包含点单、吃东西、买单几个步骤,到底吃什么则具体情况具体分析,在实际环境中再有有户动态决定。在面向对象编程中,我们可以把这些基本的步骤放到抽象类中,在抽象类中定义一个称为模板方法的方法,在这个方法中依次执行这些基本步骤(点单、吃东西、买单),这些基本步骤的实现可以延迟到具体子类。这就是模板方法模式。
单例模式重要等级★★★☆☆ 单例模式难度等级★★☆☆☆
英文定义:"Define the skeleton of an algorithm in an operation,deferring some steps to subclass. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure."
定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
模板方法模式主要包含以下角色:
(1)AbstractClass(模板类)
(2)ConcreteClass(具体子类)
在银行办理业务,一般都包含几个基本步骤:排队取号,办理业务,反馈评分。无论具体业务是取款,存款,查账还是转账,基本流程都一样,只是办理业务这一步骤不同。
通过分析,该实例类图如下:
(1)抽象类BankTemplateMethod(银行业务办理流程类)
public abstract class BankTemplateMethod
{
///
/// 模块方法process()用于指定其他方法的执行步骤。
///
public void Porcess()
{
TakeNumber();
Transact();
if (isDisplay())
{
Display();
}
Evaluate();
}
public virtual void TakeNumber()
{
Console.WriteLine("取号排队。");
}
///
/// 抽象办理业务方法,在子类中具体实现。
///
public abstract void Transact();
public virtual void Evaluate()
{
Console.WriteLine("反馈评分。");
}
public void Display()
{
Console.WriteLine("显示余额。");
}
public virtual bool isDisplay()
{
return true;
}
}
(2)具体子类Deposit(存款类)
public class Deposit : BankTemplateMethod
{
public override void Transact()
{
Console.WriteLine("存款");
}
}
(3) 具体子类Transfer(转账类)
public class Transfer : BankTemplateMethod
{
public override void Transact()
{
Console.WriteLine("转账");
}
}
(4)具体子类Audit(查账类)
public class Audit : BankTemplateMethod
{
public override void Transact()
{
Console.WriteLine("查账");
}
public override bool isDisplay()
{
return false;
}
}
(5)具体子类WithDraw(取款类)
public class WithDraw : BankTemplateMethod
{
public override void Transact()
{
Console.WriteLine("取款");
}
}
测试代码
class Program
{
static void Main(string[] args)
{
BankTemplateMethod bank;
bank= new WithDraw();
bank.Porcess();
Console.WriteLine("----------------------");
bank = new Deposit();
bank.Porcess();
Console.WriteLine("----------------------");
bank = new Audit();
bank.Porcess();
Console.WriteLine("----------------------");
bank = new Transfer();
bank.Porcess();
Console.ReadKey();
}
}
运行结果
模板方法模式是一种类的行为型模式,在它的结构图中只有类之间的继承关系,没有对象关联关系。在模板方法模式的使用过程中,要求开发抽象类和开发具体子类的设计师之间进行协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师负责给出这个算法的各个逻辑步骤。实现这些具体逻辑步骤的方法称为基本方法(Primitive Method),而将这些基本方法汇总起来的方法称为模板方法(Template Method),模板方法模式的名字由此而来,下面详细介绍模板方法和基本方法。
模板方法是定义在抽象层中,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。模板方法是一个具体的方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤可以是具体方法,也可以是抽象方法,子类继承它且不应该修改它。由于模板方法是一个具体方法,所以抽象层只能是抽象类,而不是接口。如实例中BankTemplateMethod的Process()方法。
基本方法是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)
用抽象方法定义的基本方法,意味着必须由子类具体实现,在各种语言中通常都是以abstract关键字标识。如实例中BankTemplateMethod的Transact()方法,无法在抽象类中就明确具体要办理什么业务,只能且必须由子类具体确定。
用具体方法定义的基本方法,意味着方法中的逻辑算法在抽象层就可以确定,子类可以直接继承。C# 中用关键字virtual标识方法为虚方法,则可以根据需要在子类中选择重写。
钩子方法主要分为俩类:第一类钩子方法可以于一些基本方法”挂钩“,以确定在不同的条件下执行模板方法中不同的方法,这类钩子方法的返回类型通常是布尔类型,用于对某个条件进行判断,如果条件满足则执行某一基本方法,如实例中的模板方法中的isDisplay方法。这类钩子方法实现了子类对父类行为的反向控制。
第二类钩子方法就是实现体为空的具体方法,子类可以自动继承也可以重写。这样做的好处是:因为将基本方法设计为抽象方法时,子类必须实现抽象方法。而实际情况可能子类根本不关心该抽象方法的具体实现。
(1)模板方法模式在一个类中形式化地定义算法,而由它的子类具体实现细节地处理。子类定义详细的处理算法时不会改变算法的结构。
(2)模板方法模式是一种代码复用的基本技术,他在类库设计中尤为重要,它提供了类库中的公共行为,将公共行为放在父类中,而通过子类来实现不同的行为。
(3)模板方法模式导致一种反向的控制结构,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合“开闭原则”。
每个不同的实现都需要定义一个子类,这回导致类的个数增加,系统更加庞大,设计也更加抽象,但是另一方面,这也更符合”单一职责原则“,使得类的内聚性得以提高。