一、模板方法模式概述
模板方法模式定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。(类对象型模式)
- 模板方法中的基本方法是实现算法的各个步骤,是模板方法的组成部分。基本方法又可以分为三种:
- 抽象方法:抽象方法就是在抽象类中声明并由子类实现的方法;
- 具体方法:具体方法可以由抽象类实现,或者由子类覆盖实现;
- 钩子方法:钩子方法可以由抽象类实现,子类可以加以扩展。
- 钩子方法又分为两类:
- 第一类钩子方法是可以与一些具体步骤挂钩,以实现在不同条件下执行模板方法的不同步骤,这类方法一般返回boolean,方法名一般为isXXX();
- 第二类钩子方法是实现体为空的具体方法,子类可以根据需要覆盖或者继承这些钩子方法
- 钩子方法又分为两类:
- 模板方法模式的优缺点:
- 优点:
- 1.封装不变部分,扩展可变部分;
- 2.提取公共代码,便于维护;
- 3.行为由父类控制,子类实现。
- 优点:
- 缺点:
- 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
- 使用场景:
- 1.有多个子类共有的方法,且逻辑相同;
- 2.重要的、复杂的方法,可以考虑作为模板方法。
注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。
二、代码实现
模板方法模式有两个角色:
- AbstractClass(抽象类):抽象类中定义了一系列基本操作,这些操作是具体的也可以是抽象的,每一个基本操作对应算法的一个步骤,在子类中可以重定义或实现这些步骤,同时抽象类实现了一个模板方法,定义一个算法的框架;
- ConcreteClass(具体子类):实现父类中的抽象基本方法,或者覆盖父类中具体基本操作。
2.1 抽象类
package Template.common;public abstract class AbstractClass {// 模板方法定义的框架-->这就是模板方法,是final的public final void templateMethod() {/*** 调用基本方法,完成固定逻辑* 基本操作,是由子类实现的方法*/concreteOperattion();primitiveOperation1();primitiveOperation2();if(primitiveOperation3())System.out.println("符合钩子方法条件");elseSystem.out.println("不符合钩子方法条件");primitiveOperation4();}// 抽象类的具体操作,共同的且繁琐的操作private void concreteOperattion() {// do somethingSystem.out.println("子类一定会实现的方法concreteOperattion");} public void primitiveOperation1(){System.out.println("抽象类具体方法primitiveOperation1");}// 抽象类抽象方法:由子类必须实现的操作protected abstract void primitiveOperation2();//第一类钩子方法public boolean primitiveOperation3(){return false;}//第二类钩子方法:默认不做事的方法,子类可以视情况决定要不要覆盖它public void primitiveOperation4(){}}
2.2 具体子类
package Template.common;public class ConcreteClass1 extends AbstractClass {@Overridepublic void primitiveOperation2(){System.out.println("可以不实现primitiveOperation3、primitiveOperation4,但是一定有primitiveOperation2");}public boolean primitiveOperation3(){return true;// 如果想钩子方法返回false可以不实现该方法// 因为父类默认返回false// return false;}public void primitiveOperation4(){System.out.println("子类覆盖父类第二类钩子方法");}
}
package Template.common;public class ConcreteClass2 extends AbstractClass {@Overrideprotected void primitiveOperation2() {// TODO Auto-generated method stub//必须继承的类System.out.println("可以不实现primitiveOperation3、primitiveOperation4,但是一定有primitiveOperation2");}}
2.3 main方法实现模板方法
package Template.common;public class TemplateClient {public static void main(String[] args) {// TODO Auto-generated method stubAbstractClass abstractClass1 = new ConcreteClass1();AbstractClass abstractClass2 = new ConcreteClass2();System.out.println("------ConcreteClass1-------");applyTemplate(abstractClass1);System.out.println("------ConcreteClass2-------");applyTemplate(abstractClass2);}public static void applyTemplate(AbstractClass abstractClass){abstractClass.templateMethod();}}