前言:
模板方法模式(Template Method Pattern)定义一个操作中的算法的骨架,而将一些步骤延迟到子类中去。模板模式使得子类可以不改变算法的结构既可以重定义该算法的某些特定步骤。
一.模板方法模式的简介:
模板方法模式,就是把不变的行为搬到了超类,去除子类中的重复代码,来体现他的优势。
模板方法模式的优点:
1.封装不变部分,扩展可变部分。
2.提取公共代码,便于维护。
3.行为由父类控制,子类实现。
4.提供了一个很好的代码复用平台。
应用场景: 在程序设计过程中,当遇到由一些结构相同的步骤需要执行,但这个过程从高层上看是相同的,只是有些步骤的实现可能不同,这时候就要考虑用模板方法模式了。将这些相同的步骤抽象提取到一个类中,帮助子类摆脱重复不变的行为纠缠。
二.模板方法模式的实例讲解:
案例: 在线考试系统,根据一个题库模板,自动生成多份相同的试卷,供不同考生使用。
1.UML类图:
2.试卷模板类(模板方法类):
模板抽象类,实现了多个抽象的模板方法,定义了一个算法的骨架,将重复的代码都提取到此类中,而具体的实现步骤则由子类完成。
在试卷中,试题是一样的,所以我们抽象的提取出来,而每个考生的答案不同,所以我们提供了抽象方法answer(),让不同的考生(子类)实现自己独有的答题步骤。
package com.pattern.template.template;
/**
* 模板方法类
* @author 葫芦娃
*
*/
public abstract class TemplatePaper {
public void question1() {
System.out.println("下列哪项不属于中国的四大名著?");
System.out.println("A.《西游记》;B.《水浒传》;C.《红楼梦》;D.《还珠格格》;");
}
//让子类重写,因为每个人的答案不同
protected abstract String answer1();
public void question2() {
System.out.println("下列哪项不属于面向对象的特性?");
System.out.println("A.多态;B.封装;C.重构;D.继承;");
}
//让子类重写,因为每个人的答案不同
protected abstract String answer2();
}
3.试卷类(模板方法的实现子类)
在所有子类,通过继承,即可实现父类所定义的的question()方法。子类只需要在父类的抽象方法answer()中实现自己的独有的步骤。使得每一个子类对顶级逻辑的实现都不相同。
不管有多少考生考试,只不过是填写选择题答案即可,无需在重复的抄写试题。
第一份试卷:
package com.pattern.template.concrete;
import com.pattern.template.template.TemplatePaper;
/**
* 模板方法类的实现子类
*
* @author 葫芦娃
*
*/
public class TestPaper1 extends TemplatePaper {
@Override
protected String answer1() {
System.out.println("在这实现,每个子类不同的实现步骤");
return "D";
}
@Override
protected String answer2() {
System.out.println("在这实现,每个子类不同的实现步骤");
return "C";
}
}
第二份试卷:
声明方法为protected,不对外公开这个方法,只在父类和子类中使用。
package com.pattern.template.concrete;
import com.pattern.template.template.TemplatePaper;
/**
* 模板方法类的实现子类
* @author 葫芦娃
*
*/
public class TestPaper2 extends TemplatePaper{
@Override
protected String answer1() {
System.out.println("在这实现,每个子类不同的实现步骤");
return "D";
}
@Override
protected String answer2() {
System.out.println("在这实现,每个子类不同的实现步骤");
return "D";
}
}
4.客户端(通过模板创建多份试卷)
创建多份试卷实例,只有考题的答案不同,试题全部相同。实现了对代码的复用。将重复的部分放在父类TemplatePaper中完成,具体的逻辑步骤,推迟到子类中answer()方法中完成。
package com.pattern.template.client;
import com.pattern.template.concrete.TestPaper1;
import com.pattern.template.concrete.TestPaper2;
import com.pattern.template.template.TemplatePaper;
/**
* 客户端:创建多份试卷
* @author 葫芦娃
*
*/
public class Client {
public static void main(String[] args) {
TemplatePaper studentA = new TestPaper1();
studentA.question1();
studentA.question2();
System.out.println("**************************下一份试卷******************************");
TemplatePaper studentB = new TestPaper2();
studentB.question1();
studentB.question2();
}
}
5.运行结果:
下列哪项不属于中国的四大名著?
A.《西游记》;B.《水浒传》;C.《红楼梦》;D.《还珠格格》;
下列哪项不属于面向对象的特性?
A.多态;B.封装;C.重构;D.继承;
**************************下一份试卷******************************
下列哪项不属于中国的四大名著?
A.《西游记》;B.《水浒传》;C.《红楼梦》;D.《还珠格格》;
下列哪项不属于面向对象的特性?
A.多态;B.封装;C.重构;D.继承;
三.总结:
1.当我们要完成某一细节层一致的一个过程或步骤,但步骤的更详细的实现可能不同的时候,通常考虑用模板方法模式。
2.模板方法模式给出一个顶级的逻辑骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到了子类中完成,从而实现对代码的复用。