概念
定义一个操作中的算法骨架,而将这些步骤延迟到子类中去,模板方法使得子类可以不改变一个孙发的结构即可重新定义该算法的某些特定的步骤
具体的实现
假设老师在黑板上出了一套题,让学生A和学生B将黑板上的题目抄下来做好了交上去给老师进行批改。但是学生很有可能因为一不小心将题目抄错了而将答案选错,这样就会让老师误以为这位同学没有掌握。并且,当老师改了黑板上的题目后,那么这两个同学也要跟着去修改,非常的麻烦。那么怎样解决这些问题呢?
其实老师将题目出好制作一份试卷,然后将这个试卷打印多份发给学生,这样,学生拿到的题目就是一样的了,并且学生只需要填写答案,不需要抄题,也省去了工作量。这个就是模板方法模式的体现。其中试卷就相当于是一个模板,而多个学生做这个试卷就相当于多个ConcreteClass去实现试卷这个模板中的方法。
定义试卷
public class TestPaper {
public void testQuestion1() {
System.out.println("杨过得到,后来给了郭靖," +
"炼成倚天剑、屠龙刀的玄铁可能是[ ]\n" +
"a.球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
System.out.println("答案: " + answer1());
}
public void testQuestion2() {
System.out.println("杨过、程英、陆无双铲除了情花,造成[ ]\n" +
"a.使这种植物不再伤人 b.使一种珍惜物种灭绝\n" +
"c.破坏了那个生物圈的生态平衡 d.造成该地区荒漠化");
System.out.println("答案: " + answer2());
}
public void testQuestion3() {
System.out.println("蓝凤凰致使华山师徒、桃谷六仙呕吐不止," +
"如果你是大夫,会给他们开什么药[ ]\n" +
"a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.大量生牛奶");
System.out.println("答案: " + answer3());
}
public String answer1() {
return null;
}
public String answer2() {
return null;
}
public String answer3() {
return null;
}
}
定义A同学做试卷
public class TestPaperA extends TestPaper {
@Override
public String answer1() {
return "d";
}
@Override
public String answer2() {
return "c";
}
@Override
public String answer3() {
return "c";
}
}
定义B同学做试卷
public class TestPaperB extends TestPaper {
@Override
public String answer1() {
return "a";
}
@Override
public String answer2() {
return "a";
}
@Override
public String answer3() {
return "a";
}
}
测试
public class TestPaperClient {
public static void main(String[] args) {
System.out.println("学生甲抄的试卷:");
TestPaperA studentA = new TestPaperA();
studentA.testQuestion1();
studentA.testQuestion2();
studentA.testQuestion3();
System.out.println();
System.out.println("学生乙抄的试卷:");
TestPaperB studentB = new TestPaperB();
studentB.testQuestion1();
studentB.testQuestion2();
studentB.testQuestion3();
}
}
总结
优点
- 模板方法通过把不变的行为搬移到父类,去除子类中的重复代码
- 子类实现算法的某些细节,有助于算法的拓展
- 通过一个父类调用子类实现的操作,通过子类拓展增加新的行为,符合开发-封闭的原则
缺点
- 按照设计习惯抽象类负责声明最抽象的,最一般的事物属性和方法,类负责完成具体的食物属性和方法,但是模板方法正好相反,子类执行的结构影响到父类的结构,会增加阅读的难度
模板方法适合使用的场景
- 多个子类共有的方法,并且操作逻辑基本相同
- 重要的,复杂的算法,可以把核心算法设计成模板方法,周边的相关的细节则由子类实现
- 重构时,模板方法时经常使用的方法,把相同的代码抽取到父类中,然后通过构造函数去约束其行为