一,定义
模板方法模式,定一个操作中的算法的骨架,而将一些步骤延迟到到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
二,实例
我们将实现一个,测试题类(选择题),由学生来答题的例子
public abstract class TestPaper { //测试题
public void TestQuestionA(){
System.out.println("你最喜欢的编程语言[ ] A:JAVA B:C++ C:IOS D:Python");
System.out.println("我的答案:" + TestAnswerA());
}
public void TestQuestionB(){
System.out.println("你最头疼的编程语言[ ] A:JAVA B:C++ C:IOS D:Python");
System.out.println("我的答案:" + TestAnswerB());
}
public abstract String TestAnswerA();
public abstract String TestAnswerB();
}
public class StudentA extends TestPaper {
public StudentA(){
System.out.println("学生A开始答题:");
}
@Override
public String TestAnswerA() {
return "C";
}
@Override
public String TestAnswerB() {
return "D";
}
}
//验证
public static void templateMethod(){
TestPaper studentA = new StudentA();
studentA.TestQuestionA();
studentA.TestQuestionB();
TestPaper studentB = new StudentB();
studentB.TestQuestionA();
studentB.TestQuestionB();
}
输出结果:
学生A开始答题:
你最喜欢的编程语言[ ] A:JAVA B:C++ C:IOS D:Python
我的答案:C
你最头疼的编程语言[ ] A:JAVA B:C++ C:IOS D:Python
我的答案:D
学生B开始答题:
你最喜欢的编程语言[ ] A:JAVA B:C++ C:IOS D:Python
我的答案:A
你最头疼的编程语言[ ] A:JAVA B:C++ C:IOS D:Python
我的答案:D
模板方法模式是通过把不变的行为搬到超类,去除子类中的重复代码来体现它的优势。
三,模版方法模式的结构
模版方法模式由一个抽象类和一个(或一组)实现类通过继承结构组成,抽象类中的方法分为三种:
- 抽象方法:父类中只声明但不加以实现,而是定义好规范,然后由它的子类去实现。
- 模版方法:由抽象类声明并加以实现。一般来说,模版方法调用抽象方法来完成主要的逻辑功能,并且,模版方法大多会定义为final类型,指明主要的逻辑功能在子类中不能被重写。
- 钩子方法:由抽象类声明并加以实现。但是子类可以去扩展,子类可以通过扩展钩子方法来影响模版方法的逻辑。
抽象类的任务是搭建逻辑的框架,通常由经验丰富的人员编写,因为抽象类的好坏直接决定了程序是否稳定性。
实现类用来实现细节。抽象类中的模版方法正是通过实现类扩展的方法来完成业务逻辑。只要实现类中的扩展方法通过了单元测试,在模版方法正确的前提下,整体功能一般不会出现大的错误。
四,总结
模板方法模式就是提供了一个很好的代码复用平台,当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现,我们通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复不变行为的纠缠。总的来说有以下有点:
- 1,容易扩展。一般来说,抽象类中的模版方法是不易反生改变的部分,而抽象方法是容易反生变化的部分,因此通过增加实现类一般可以很容易实现功能的扩展,符合开闭原则。
- 2,便于维护。对于模版方法模式来说,正是由于他们的主要逻辑相同,才使用了模版方法,假如不使用模版方法,任由这些相同的代码散乱的分布在不同的类中,维护起来是非常不方便的。
- 3,比较灵活。因为有钩子方法,因此,子类的实现也可以影响父类中主逻辑的运行。但是,在灵活的同时,由于子类影响到了父类,违反了里氏替换原则,也会给程序带来风险。这就对抽象类的设计有了更高的要求。
使用场景:在多个子类拥有相同的方法,并且这些方法逻辑相同时,可以考虑使用模版方法模式。在程序的主框架相同,细节不同的场合下,也比较适合使用这种模式。
参考:《大话设计模式》 http://blog.csdn.net/zhengzhb/article/details/7405608