设计模式学习总结-模板方法模式(Template Method)
问题:
在面向对象系统的分析与设计过程中经常会遇到,对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现,但是逻辑(算法)的框架(或通用的应用算法)是相同的。这时候我们一般需要把逻辑(算法)框架放在抽象基类中,并定义好细节的接口,采用继承的方式在子类中实现细节。
定义:
模板方法模式是类的行为模,定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可以重定义算法的某些特定步骤。
意图:
Template是采用继承的方式实现算法的异构,将通用算法封装在抽象基类中,并将不同的算法细节放到子类中实现,使得子类可以置换掉父类的可变部分,但是子类却不可以改变模板方法所代表的顶级逻辑。
使用了面向对象设计中的DIP(依赖倒置:Dependency Inversion Principles)原则。实现父类调用子类的操作,子类(低层模块)实现父类(高层模块)声明的接口。这样控制权在父类(高层模块),低层模块反而要依赖高层模块。实现反向控制结构效果。
参与者:
•AbstractClass(抽象模版)角色:
定义了一个或多个抽象的作基本方法(Primitive Method),以便让子类实现。它们是一个模版方法(Template Method)的组成的具体逻辑步骤。
定义并实现了一个模版方法。这个模版方法一般是一个具体方法,它给出一个逻辑骨架,而逻辑的组成步骤在相应的抽象基本方法(Primitive Method)中,推迟到子类实现。
•ConcreteClass(具体模版)角色:
实现父类所定义的一个或多个抽象方法。
每一个抽象模版角色都可以有任意多个具体模版角色与之对应,而每一个具体模版角色都可以给出这些抽象方法的不同实现,从而将算法细节让子类实现(多态)。
UML:
实例说明:
诺基亚手机工厂
对于手机生产,N8,N9有一定的生产差异,比如CPU,内存有不同的安装方式,但是,实现生产步骤都是一样的。
uml图如下:
代码:
/// 手机生产 抽象模板
/// </summary>
public abstract class AbstractCreatePhone
{
/// <summary>
/// 安装主板(抽象行为)
/// </summary>
public abstract void BuildMb();
public abstract void BuildCpu();
public abstract void SetSystem();
/// <summary>
/// 模板方法 给出逻辑架构
/// </summary>
public void CreatePhone()
{
BuildMb();
BuildCpu();
SetSystem();
System.Console.WriteLine("手机生产完成!");
}
}
/// <summary>
/// N8手机生产具体类
/// </summary>
public class ConcreteCreateN8 : AbstractCreatePhone
{
public ConcreteCreateN8()
{
System.Console.WriteLine("开始生产N8!");
}
public override void BuildMb()
{
System.Console.WriteLine("N8主板安装完成!");
}
public override void BuildCpu()
{
System.Console.WriteLine("N8 CPU 安装完成!");
}
public override void SetSystem()
{
System.Console.WriteLine("N8 系统 安装完成!");
}
}
/// <summary>
/// N8手机生产具体类
/// </summary>
public class ConcreteCreateN9 : AbstractCreatePhone
{
public ConcreteCreateN9()
{
System.Console.WriteLine("开始生产N9!");
}
public override void BuildMb()
{
System.Console.WriteLine("N9主板安装完成!");
}
public override void BuildCpu()
{
System.Console.WriteLine("N9 CPU 安装完成!");
}
public override void SetSystem()
{
System.Console.WriteLine("N9 系统 安装完成!");
}
}
/// <summary>
/// 客户端测试代码
/// </summary>
public void TemplateMethodTest()
{
//实例化生产类
AbstractCreatePhone acp = new ConcreteCreateN8();
//生产手机
acp.CreatePhone();
}
优点:
•模板方法模式通过把不变的行为放在基类,去除了子类中的重复代码、保证了逻辑的统一性。
•子类实现算法的某些细节,有助于算法的扩展(多态)。
•父类的模板方法控制子类的具体使用,使得我们不用过于关心父类的全部业务流程。
缺点:
•算法的骨架有改变的话,需要改变抽象类,违背了“开闭原则”。
应用情景:
•一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
•要完成在某一具有相同步骤的算法,但个别步骤在不同场景中有不同实现时。