模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。UML结构图如下:
下面以考试试卷,不同学生选择不同答案来进行举例:
参与角色:
- 抽象类
- 具体方法(即重复的方法)
- 抽象空方法(子类自己实现的方法,子类实现的方法是个性化的)
抽象类:
/**
* 抽象测试试卷:将子类重复的代码抽取在此,并且把子类中不同的部分抽象成方法,由子类去实现
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public abstract class TestPaper {
private String name;
public TestPaper(String name){
this.name = name;
}
/**
* 问题1(具体的重复方法)
*/
public void testQuestion01(){
System.out.println("1.关于Java编译,下面哪一个正确()(选择一项)");
System.out.println("A.Java程序经编译后产生machine code");
System.out.println("B.Java程序经编译后会生产byte code");
System.out.println("C.Java程序经编译后会产生DLL");
System.out.println("D.以上都不正确");
System.out.println(name + "选择的答案是:" + answer01());
}
/**
* 问题2
*/
public void testQuestion02(){
System.out.println("2.下列说法正确的有()(选择一项)");
System.out.println("A.class中的construtor不可省略");
System.out.println("B.construtor与class同名,但方法不能与class同名");
System.out.println("C.construtor在一个对象被new时执行");
System.out.println("D.一个class只能定义一个construtor");
System.out.println(name + "选择的答案是:" + answer02());
}
/**
* 问题3
*/
public void testQuestion03(){
System.out.println("3.Java中接口的修饰符可以为()(选择一项)");
System.out.println("A.private");
System.out.println("B.protected");
System.out.println("C.final");
System.out.println("D.abstract");
System.out.println(name + "选择的答案是:" + answer03());
}
/**
* 不同的人选择不同的答案,抽象成空方法
* @return
*/
protected abstract String answer01();
protected abstract String answer02();
protected abstract String answer03();
}
学生A的试卷答案,具体实例:
/**
* 学生A的试卷答案
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class StudentPaperA extends TestPaper{
public StudentPaperA(String name) {
super(name);
}
/**
* 第一题答案
* @return
*/
@Override
protected String answer01() {
return "B";
}
/**
* 第二题答案
* @return
*/
@Override
protected String answer02() {
return "C";
}
/**
* 第三题答案
* @return
*/
@Override
protected String answer03() {
return "D";
}
}
学生B的试卷答案,具体实例:
/**
* 学生B的试卷答案
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class StudentPaperB extends TestPaper{
public StudentPaperB(String name) {
super(name);
}
@Override
protected String answer01() {
return "A";
}
@Override
protected String answer02() {
return "B";
}
@Override
protected String answer03() {
return "C";
}
}
测试:
/**
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class Main {
/**
* 模板方法:
* 1.一套试卷,题目共享,相当于复制一份,每个同学选择不同的答案
* @param args
*/
public static void main(String[] args) {
TestPaper studentA = new StudentPaperA("小明");
studentA.testQuestion01();
studentA.testQuestion02();
studentA.testQuestion03();
System.out.println("=================================");
TestPaper studentB = new StudentPaperB("小张");
studentB.testQuestion01();
studentB.testQuestion02();
studentB.testQuestion03();
}
}

模板方法总结:
该模式的主要优点如下:
- 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
- 它在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
该模式的主要缺点如下:
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统实现的复杂度。
- 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
- 由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。
1338

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



