1.模式动机与定义
模板方法定义:定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的特定步骤。
模板方法是一种行为型模式。
2.模式结构与分析
/** * 实现了一个模板方法,定义了算法的骨架。 * 具体子类将重新定义primitiveMethod()以实现一个算法的步骤 * * 注意:是抽象类,不是接口。 * 为什么不是接口?因为templateMethod()方法有具体的方法体。 */public abstract class AbstractClass { public void templateMethod() { primitiveOperation1(); primitiveOperation2(); System.out.println("这里是算法骨架中的一些共用的操作"); } protected abstract void primitiveOperation1(); protected abstract void primitiveOperation2();}
/** * 具体类A */public class ConcreteClassA extends AbstractClass { @Override protected void primitiveOperation1() { System.out.println("具体类A的方法1实现"); } @Override protected void primitiveOperation2() { System.out.println("具体类A的方法2实现"); }}
/** * 具体类B */public class ConcreteClassB extends AbstractClass { @Override protected void primitiveOperation1() { System.out.println("具体类B的方法1实现"); } @Override protected void primitiveOperation2() { System.out.println("具体类B的方法2实现"); }}
客户端代码如下。
public class Client { public static void main(String[] args) { AbstractClass c; c = new ConcreteClassA(); c.templateMethod(); System.out.println("----------------"); c = new ConcreteClassB(); c.templateMethod(); }}/** * 输出如下: 具体类A的方法1实现 具体类A的方法2实现 这里是算法骨架中的一些共用的操作 ---------------- 具体类B的方法1实现 具体类B的方法2实现 这里是算法骨架中的一些共用的操作 */
3.模式实例与解析
模式实例:
在学生做测试试卷的场景中,测试试卷中会含有n多个选择题。如果将测试试卷看做一个考试流程的话,每个选择题可以看做是其中的一个步骤。 而对于每个考生的具体试卷来说,除了考生的答案之外,考卷上的内容(包括题目和选项)都是一样的。/** * 测试试卷类,包含了题目和选项。 * 学生仅仅填写答案就可以. * (在此场景中,可将测试试卷看做定义了考试流程的框架。) */public abstract class TestPaper { public void testQuestion1() { System.out.println("测试题目1: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww"); System.out.println("你的答案为:" + answer1()); } public void testQuestion2() { System.out.println("测试题目2: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww"); System.out.println("你的答案为:" + answer2()); } public void testQuestion3() { System.out.println("测试题目3: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww"); System.out.println("你的答案为:" + answer3()); } protected abstract String answer1(); protected abstract String answer2(); protected abstract String answer3();}
/** * 学生A的试卷 * (在此场景中,可将学习添加答案,看做自己考试流程中的步骤细节) */public class TestPaperA extends TestPaper { @Override protected String answer1() { return "A"; } @Override protected String answer2() { return "A"; } @Override protected String answer3() { return "A"; }}
/** * 学生B的试卷 */public class TestPaperB extends TestPaper { @Override protected String answer1() { return "B"; } @Override protected String answer2() { return "B"; } @Override protected String answer3() { return "B"; }}
public class Client { public static void main(String[] args) { TestPaper testPaperA = new TestPaperA(); testPaperA.testQuestion1(); testPaperA.testQuestion2(); testPaperA.testQuestion3(); System.out.println("-------------------------------------"); TestPaper testPaperB = new TestPaperB(); testPaperB.testQuestion1(); testPaperB.testQuestion2(); testPaperB.testQuestion3(); }}/** *输出如下: 测试题目1: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww 你的答案为:A 测试题目2: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww 你的答案为:A 测试题目3: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww 你的答案为:A ------------------------------------- 测试题目1: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww 你的答案为:B 测试题目2: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww 你的答案为:B 测试题目3: xxxxxx,下面答案正确的是。A.xxxx B.yyyy C.zzzz D.wwww 你的答案为:B */
4.模式效果与应用
- 模板方法模式在一个类中形式化地定义算法,而由它的子类实现细节的处理。 模板方法模式的优势是,在子类定义详细的处理算法时不会改变算法的结构。模板方法模式就是体现继承优势的模式之一
- 模板方法是一种代码复用的基本技术,它们在类库中尤为重要,它们提取了类库中的公共行为。 其主要应用于框架设计,以确保父类控制处理流程的逻辑顺序(如框架的初始化)。
- 在模板方法模式中,子类不显式调用父类的方法,而是通过覆盖父类的方法来实现某些具体的业务逻辑,父类控制对子类的调用,这种机制被称为好莱坞原则(Hollywood Principle),即“不要给我们打电话,我们会给你打电话(Don‘t call us, we’ll call you)”。在模板方法模式中,好莱坞原则体现在:子类不需要调用父类,而通过父类来调用子类,将某些步骤的实现写在子类中,由父类来控制整个过程。