一、什么是模板方法模式##
定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法是的子类可以不改变一个算法结构即可重定义该算法的某些特定步骤【DP】
通俗地说,就是将重复的步骤通过搬移到超类里面,去除子类的重复代码
二、模板方法模式的模型
UML图:
![这里写图片描述](https://img-blog.csdn.net/20150915123453106)
代码:
/**
* 抽象类,提供模板方法,但是其实现需要推迟到子类
*/
public abstract class AbstractClass {
/**
* 抽象操作1
*/
public abstract void primitiveOperation1();
/**
* 抽象操作2
*/
public abstract void primitiveOperation2();
/**
* 模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,它们都推迟到了子类实现
*/
public void templateMethod() {
primitiveOperation1();
primitiveOperation2();
System.out.println("");
}
}
/**
* 具体类A,实现抽象类的一些抽象操作
*/
public class ConcreteClassA extends AbstractClass{
/**
* 实现抽象类的抽象操作1
*/
@Override
public void primitiveOperation1() {
System.out.println("具体类A方法1的实现");
}
/**
* 实现抽象类的抽象操作2
*/
@Override
public void primitiveOperation2() {
System.out.println("具体类A方法2的实现");
}
}
/**
* 具体类B,实现抽象类的抽象操作,但是实现方式不同
*/
public class ConcreteClassB extends AbstractClass{
/**
* 实现抽象操作1的另一种方法
*/
@Override
public void primitiveOperation1() {
System.out.println("具体类B方法1的实现");
}
/**
* 实现抽象操作2的另一种方法
*/
@Override
public void primitiveOperation2() {
System.out.println("具体类B方法2的实现");
}
}
/**
* 客户端类,用于测试
*/
public class Client {
public static void main(String[] args) {
AbstractClass abstractClass;
abstractClass = new ConcreteClassA();
abstractClass.templateMethod();
abstractClass = new ConcreteClassB();
abstractClass.templateMethod();
}
}
三、一个例子
例子背景:
用模板方法模式来模拟下面的过程:
抄试卷,比如老师在黑板上写出试题,学生每个人都需要抄一份,并且写上自己的答案。
这种情况下,我们希望学生抄的题目都是一样的,而不同的应该就在于每个人的答案
所以,抄试题的过程是重复的,写上自己的答案的过程是不同的
代码:
/**
* 该类是学生抄试题和填写答案的超类
*/
public class AllStudent {
/**
* 抄写题目1和书写其答案
*/
public void question1(){
System.out.println("这是试题1, 答案是: " + answer1());
}
/**
* 抄写题目2和书写其答案
*/
public void question2(){
System.out.println("这是试题2, 答案是: " + answer2());
}
/**
* 抄写题目3和书写其答案
*/
public void question3(){
System.out.println("这是试题3, 答案是: " + answer3());
}
/**
* 模拟书写题目1的答案
* @return 返回书写答案
*/
protected String answer1(){
return "";
}
/**
* 模拟书写题目2的答案
* @return 返回书写答案
*/
protected String answer2(){
return "";
}
/**
* 模拟书写题目3的答案
* @return 返回书写答案
*/
protected String answer3(){
return "";
}
}
/**
* 学生A抄写题目与回答题目, 因为题目的抄写应该每个学生都是一直的,所以这里只要重写父类回答问题的方法
*/
public class StudentA extends AllStudent{
@Override
protected String answer1() {
return "学生A对题目1的回答";
}
@Override
protected String answer2() {
return "学生A对题目2的回答";
}
@Override
protected String answer3() {
return "学生A对题目3的回答";
}
}
/**
* 学生B抄写题目与回答题目, 因为题目的抄写应该每个学生都是一直的,所以这里只要重写父类回答问题的方法
*/
public class StudentB extends AllStudent {
@Override
protected String answer1() {
return "学生B对题目1的回答";
}
@Override
protected String answer2() {
return "学生B对题目2的回答";
}
@Override
protected String answer3() {
return "学生B对题目3的回答";
}
}
/**
* 客户端类,用于测试
*/
public class Client {
public static void main(String[] args) {
AllStudent student;
student = new StudentA();
student.question1();
student.question2();
student.question3();
student = new StudentB();
student.question1();
student.question2();
student.question3();
}
}
四、模板方法的使用场合
要完成在某一细节层次的一个过程或一系列步骤,但是个别步骤在更详细的层次上的实现可能不同的时候,我们就可以考虑使用模板模式。
五、模板方法模式的提出原因
在开发过程中我们通常遇到这样的情况:就是我们要实现一个过程或者一系列步骤,这些步骤可能在更详细的层次上的实现会稍有不同,而大部分或者逻辑骨架是相同的,因为重复=易错+难修改(一错导致多出错、一改要多处修改),所以有必要把重复的步骤或者骨架提取出来,这样修改维护起来就容易多了。