Template Method模式

1.定义:一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。

类型:行为类模式

类图:


2.模板模式与继承
    模板方法估计恰当地使用继承。此模式可以用来改写一些拥有相同功能的相关的类,将可复用的一般性行为代码移到基类里面,而把特殊化的行为代码移到子类里面。熟悉模板方法模式是重新学习继承的开始。

3.模板模式的方法
1)模板方法:必须由抽象类实现,该方法是一个顶级逻辑,调用任意多个基本方法。子类不应该修改该方法

2)基本方法:模板方法所调用的方法,有可细分为抽象方法,具体方法,钩子方法
    抽象方法:强迫子类重写的
    具体方法:不需要子类重写的,最好声明为final
    钩子方法:子类可以重写的,一般是个空方法(钩子方法的命名应该以do开头,这是一个通用规范)
补充:模板模式的设计理念是尽量减少必须由子类置换掉的基本方法的数量(可以理解为尽量减少抽象方法和钩子方法的数量。)

4 钩子方法的使用

       模板方法模式中,在父类中提供了一个定义算法框架的模板方法,还提供了一系列抽象方法、具体方法和钩子方法,其中钩子方法的引入使得子类可以控制父类的行为。最简单的钩子方法就是空方法,代码如下:

public virtual void Display() {   }  

      当然也可以在钩子方法中定义一个默认的实现,如果子类不覆盖钩子方法,则执行父类的默认实现代码。

      另一种钩子方法可以实现对其他方法进行约束,这种钩子方法通常返回一个bool类型,即返回truefalse,用来判断是否执行某一个基本方法,下面通过一个实例来说明这种钩子方法的使用。

      某软件公司欲为销售管理系统提供一个数据图表显示功能,该功能的实现包括如下几个步骤:

      (1) 从数据源获取数据;

      (2) 将数据转换为XML格式;

      (3) 以某种图表方式显示XML格式的数据。

      该功能支持多种数据源和多种图表显示方式,但所有的图表显示操作都基于XML格式的数据,因此可能需要对数据进行转换,如果从数据源获取的数据已经是XML数据则无须转换。

       由于该数据图表显示功能的三个步骤次序是固定的,且存在公共代码(例如数据格式转换代码),满足模板方法模式的适用条件,可以使用模板方法模式对其进行设计。因为数据格式的不同,XML数据可以直接显示,而其他格式的数据需要进行转换,因此第(2)步“将数据转换为XML格式”的执行存在不确定性,为了解决这个问题,可以定义一个钩子方法IsNotXMLData()来对数据转换方法进行控制。通过分析,该图表显示功能的基本结构如图4所示:

图1 数据图表显示功能结构图

       可以将公共方法和框架代码放在抽象父类中,代码如下:

public abstract class DataViewer {

	// 抽象方法:获取数据
	public abstract void GetData();

	// 具体方法:转换数据
	public void ConvertData() {
		System.out.println("将数据转换为XML格式。");
	}

	// 抽象方法:显示数据
	public abstract void DisplayData();

	// 钩子方法:判断是否为XML格式的数据
	public boolean IsNotXMLData() {
		return true;
	}

	// 模板方法
	public void Process() {
		GetData();
		// 如果不是XML格式的数据则进行数据转换
		if (IsNotXMLData()) {
			ConvertData();
		}
		DisplayData();
	}
}

public class XMLDataViewer extends DataViewer{

	@Override
	public void GetData() {
		// TODO Auto-generated method stub
		System.out.println("从XML文件中获取数据。");
	}

	@Override
	public void DisplayData() {
		// TODO Auto-generated method stub
		System.out.println("以柱状图显示数据。");
	}
	//覆盖父类的钩子方法  
	@Override
    public boolean IsNotXMLData()  
    {  
        return false;  
    }  

}

public class Client {

	public static void main(String args[]) {
		DataViewer dv;
		dv = new XMLDataViewer();
		dv.Process();
	}
}

优点与缺点:

模板方法模式的主要优点如下:

       (1) 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。

       (2) 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。

       (3) 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。

       (4) 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。

      (5)需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。

模式适用场景

在以下情况下可以考虑使用模板方法模式:

  (1) 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。即:一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。

  (2) 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。

  (3) 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

  



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值