模板方法模式 : 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法的特点:提供了一个很好的代码复用平台。模板方法模式通过把不变的行为搬移到超类,去除子类中的重复代码来体现优势。
模板方法模式的结构图如下:
AbstractClass是抽象类,定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出一个顶级逻辑的架构,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也可以调用一些具体的方法。
下面举例如下:
假设有三角形、圆形三种图形,每种图形向控制台输出自己的周长和面积计算公式。
public abstract class Shape {
protected String name;
public Shape(String name){
this.name = name;
}
public void OutPutOperationMethod(){
System.out.println("I am " + name);
System.out.print("Perimeter : ");
Perimeter();
System.out.print(" Area : ");
Area();
System.out.println();
}
public abstract void Perimeter();
public abstract void Area();
public static void main(String[] args){
Shape t1 = new Triangle("Triangle");
Shape c1 = new Circle("Circle");
t1.OutPutOperationMethod();
c1.OutPutOperationMethod();
}
}
class Triangle extends Shape{
public Triangle(String name){
super(name);
}
public void Perimeter(){
System.out.println("C = a + b + c ");
}
public void Area(){
System.out.println("S = 1 / 2 * a * h.");
}
}
class Circle extends Shape{
public Circle(String name){
super(name);
}
public void Perimeter(){
System.out.println("C = 2 * PI * r");
}
public void Area(){
System.out.println("S = PI * r * r");
}
}
OK。这就是一个简单的模板方法模式,这样做的好处是什么的呢。假设现在需求变了,老师要求我们将周长面积公式各抄10遍。此时我们只需修改抽象类中的OutPutOperationMethod方法。将其修改如下:
public void OutPutOperationMethod(){
System.out.println("I am " + name);
for( int i = 0; i < 10; ++ i){
System.out.print("Perimeter : ");
Perimeter();
System.out.print(" Area : ");
Area();
System.out.println();
}
}
也就是说相同的操作只需修改模板类。从而避免了修改各个子类。如果OutPutOperationMethod方法是在各个子类中实现的,那么当需求变更时需要修改每一个子类。不仅修改的量增加,而且随着修改次数的增加,错误以及遗漏的风险也将增大。如果有100中图形子类,工作量和错误出现的概率岂不很大?