定义一个方法时,其中一部分是固定的,但有一部分不确定,需要经常替换,而固定的部分又要使用不确定的部分。那么就将不确定的部分暴露出去,由该类的子类去完成。
而这固定的部分就像是一个模板一样,可以经常重复使用。
借用一个图来说明:

代码举例:
class GetTime{
public final void getTime()
{
long start = System.currentTimeMillis();
for(int x=0; x<4000; x++)
{
System.out.print(x);
}
long end = System.currentTimeMillis();
System.out.println("millisecond:"+ (end - start));
}
}
class TemplateDemo
{
public static void main(String[] args)
{
GetTime gt = new GetTime();
gt.getTime();
}
}
for 循环这里面的代码是getTime()需要去计算其运行时间的。为了计算其他代码的运行时间,我们就必须要使用新代码代替这部分代码,然后重新编译运行。每次都需要改动这个类的源代码,使得结构不清晰,以及使用的困难,程序员需要读这部分代码,然后决定替换哪部分代码。这容易造成代码的错误和不安全。为了解决这部分问题,我们把要计算运行时间的这段代码拿出来单独作为一个方法,并且创建一个子类继承这个类,让子类中定义相同的方法去覆盖父类中的方法,从而计算子类中方法运行的时间。
优化后的代码如下:
class GetTime{
public void getTime()
{
long start = System.currentTimeMillis();
runcode();
long end = System.currentTimeMillis();
System.out.println("millisecond:"+ (end - start));
}
public void runcode()
{
for(int x=0; x<1000; x++)
{
System.out.print(x);
}
}
}
class SubTimeextends GetTime
{
public void runcode()// 覆盖了父类中的runcode方法
{
for(int x=0; x<4000; x++)
{
System.out.print(x);
}
}
}
class TemplateDemo
{
public static void main(String[] args)
{
SubTime gt = new SubTime();
gt.getTime();
}
}
我们发现父类中的runcode方法其实在以后的使用中每次都要被覆盖,因为子类每次要运行的runcode的方法都是不确定的,因此我们这类把父类中的runcode方法改为abstract类型。
优化后的父类代码:
abstractclass GetTime{
public final void getTime()//这个功能不允许子类复写,
//因为它是实现功能所必须的,
//所以使用final关键字
{
long start = System.currentTimeMillis();
runcode();
long end = System.currentTimeMillis();
System.out.println("millisecond:"+ (end - start));
}
public abstract void runcode();//这里可以不用抽象类,因为父类可以首先定义一些可用的代码,不过允许子类重写覆盖
}
什么时候使用模板模式?
1) 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
2) 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。其实这可以说是一种好的编码习惯了。
3) 控制子类扩展。模板方法只在特定点调用操作,这样就只允许在这些点进行扩展。如果你不愿子类来修改你的模板方法定义的框架,你可以采用两种方式来做:一是在API中不体现出你的模板方法;二、将你的模板方法置为final就可 以了。
可以看出,使用模板方法模式可以将代码的公共行为提取出来,达到复用的目的。而且,在模板方法模式中,是由父类的模板方法来控制子类中的具体实现。这样你在实现子类的时候,根本不需要对业务流程有太多的了解。

768

被折叠的 条评论
为什么被折叠?



