模板模式
Template Method模式是带有模板功能的模式,组成模板的方法被定义在父类中。由于这些方法是抽象方法,所以只查看父类的代码是无法知道这些方法最终会进行何种具体处理的,唯一能知道的就是父类是如何调用这些方法的。
实现上述这些抽象方法的是子类。在子类中实现了抽象方法也就决定了具体的处理。
也就是说,只要在不同的子类中实现不同的具体处理,当父类的模板方法被调用时程序行为也会不同。但是,不论子类中的具体实现如何,处理的流程都会按照父类中所定义的那样进行。
像这样在父类中定义处理流程的框架,在子类中实现具体处理的模式就称为Template Method模式。
—— 《图解设计模式》
我们先来看一个例子:
A类中有一个计算累计和的方法,并且输出了程序执行时间。
public class A {
public void job(){
long start = System.currentTimeMillis();
long num = 0;
for (int i = 1; i <= 10000000; i++) {
num += i;
}
long end = System.currentTimeMillis();
System.out.println("A执行时间 " + (end - start));
}
}
如果B类有一个累乘的方法,并且也输出了程序执行时间
public class B {
public void job(){
long start = System.currentTimeMillis();
long num = 0;
for (int i = 1; i <= 800000; i++) {
num *= i;
}
long end = System.currentTimeMillis();
System.out.println("B执行时间 " + (end - start));
}
}
调用的时候如下
public static void main(String[] args) {
A a = new A();
a.job();
B b = new B();
b.job();
}
通过以上代码我们发现,A类中的job方法和B类中的job方法有重复的代码,相似的结构,为此作以下改进:
A类中把计算执行时间的方法抽离出来放到calculateTime方法里,然后在该方法里调用计算方法job
public class A {
public void calculateTime(){
long start = System.currentTimeMillis();
job();
long end = System.currentTimeMillis();
System.out.println("A执行时间 " + (end - start));
}
public void job(){
long num = 0;
for (int i = 1; i <= 10000000; i++) {
num += i;
}
}
}
B类也跟A类一样
public class B {
public void calculateTime(){
long start = System.currentTimeMillis();
job();
long end = System.currentTimeMillis();
System.out.println("B执行时间 " + (end - start));
}
public void job(){
long num = 0;
for (int i = 1; i <= 800000; i++) {
num *= i;
}
}
}
调用的时候如下
public static void main(String[] args) {
A a = new A();
a.calculateTime();
B b = new B();
b.calculateTime();
}
但是如果有C类也需要类似的功能,这样做在每个类里都定义一个calculateTime方法,还是显得冗余。仔细观察会发现A类和B类都有相同的calculateTime方法,这时我们想到了继承。可以定义一个抽象父类Template,在父类里面定义一个calculateTime方法,然后声明一个抽象的job方法,在calculateTime方法里调用job方法,让A类和B类继承Template类,各自实现不同的计算方法job,这样就完美解决了问题。
public abstract class Template {
public abstract void job();
public void calculateTime(){
long start = System.currentTimeMillis();
job();
long end = System.currentTimeMillis();
System.out.println("程序执行时间 " + (end - start));
}
}
public class A extends Template{
@Override
public void job() {
long num = 0;
for (int i = 1; i <= 10000000; i++) {
num += i;
}
}
}
public class B extends Template{
@Override
public void job() {
long num = 0;
for (int i = 1; i <= 800000; i++) {
num *= i;
}
}
}
调用的时候如下
public static void main(String[] args) {
Template a = new A();
a.calculateTime(); //由于A类没有calculateTime方法,因此会向上找,使用父类的calculateTime方法,当执行到job的时候,会遵循动态绑定机制,回到子类调用job方法
Template b = new B();
b.calculateTime();
}
模板设计模式是抽象类的一个应用,在抽象类中确定处理的流程,然后再由子类去做不同的实现,这样可以使逻辑处理通用化,并且提高了代码的复用性。