
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
前言
国际惯例,本文仍然是在学习设计模式的路上所写,希望对同样在学习设计模式的童靴有点作用,大牛误入的话还请给点宝贵意见,感激不尽。
定义
网络定义
定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式可以不改变一个算法的结构即可重定义该算法的某些特定的步骤。
个人拙见
模板方法模式是一种基于继承的代码的复用形式,将一个操作中的固定不变的部分定义在基类的模板方法中,并且在抽象基类中给出抽象方法用以在子类中实现,在扩展子类时不需要去改变原来的基类,满足开闭原则,但是各个子类中都有各自的特性,因此破坏了里式替换原则,模板方法模式是一个类行为型模式,总结起来就是在基类中定义模板,在子类中实现特定的步骤,基类可以有任意多个子类。
类图
代码实现
模板方法中主要是两类角色,一个是抽象的模板类,一个是具体的实现类,下面给出JAVA实现的模板类和一个具体的实现类。
模板类:
publicabstractclassAbstractTemplate{//模板方法publicfinalvoidtemplateMethod(){ System.out.println("模板方法执行开始"); abstractMethod();if(isExecute()){ System.out.println("子类的方法返回true,执行下面的方法"); concreteMethod(); } System.out.println("模板方法执行结束"); }//抽象方法publicabstractvoidabstractMethod();//hookMethodpublicabstractbooleanisExecute();//实现方法publicvoidconcreteMethod(){ System.out.println("在基类中实现的方法"); } }
实现类:
publicclassConcreteTemplateextendsAbstractTemplate{privatebooleanflag;publicConcreteTemplate(booleanflag){this.flag = flag; }@OverridepublicvoidabstractMethod(){ System.out.println("需要在子类中实现的方法"); }@OverridepublicbooleanisExecute(){returnflag; } }
测试类:
publicclassTest {publicstaticvoidmain(String[] args){ AbstractTemplateabs=newConcreteTemplate (true);abs.templateMethod(); } }
测试结果:
理解
模板类中的方法
模板类中的方法大致可以分为四个类型,分别是模板方法(templateMethod)、抽象方法(abstractMethod和isExecute)、实现方法(concreteMethod)、子类选择实现的方法(method),当然,抽象方法又可以分为两种,一种确实是需要子类实现的抽象方法,一种又称之为钩子方法(isExecute),下面一个一个来说各个方法的作用:
模板方法
模板方法是整个模板类或者说是模板方法模式的核心,在这个方法中定义了某个算法的骨干或者某件事情的流程以及组成部分,这个方法中的内容是固定不变的,不管有多少个子类继承模板类,这个方法都不应该发生改变,并且在大多数情况下这个方法应该被定义成final类型的,如同上述测试类中的templateMethod方法,这个方法是需要在模板类中进行实现的,在实现过程中定义算法骨干或者事件流程;
抽象方法
在模板类中定义的抽象方法是需要在子类中去实现的,是算法或者流程的具体实现过程,在父类中定义抽象方法,在不同的子类中进行不同的实现,运行时根据调用子类的不同而进行不同的步骤,如同上述模板类中的abstractMethod方法;
实现方法
在模板类中已经实现的方法,除了核心的模板方法之外,其他的已实现方法是共用的方法,也就是说不管是多少子类,这个方法都可以使用,当然也可以在子类中覆盖这个方法,但是这样的话如果替换子类,那么模板方法的实现过程可能就发生了变化,在实现方法中有一个特例,就是方法范围的修饰符是protected,此时你也可以在模板类中给出一个空实现,在子类需要的时候再去重写这个方法,如同上面代码中的method方法,这样就可以在特定的子类中添加特定的实现,其他不需要实现的子类就默认使用基类的空实现即可。
钩子方法
所谓的钩子方法其实就是一个通过子类方法的返回值来控制父类的模板方法执行流程的方法,如同上述例子中的isExecute方法,在模板类中是一个抽象方法,返回值是boolean类型的,具体的实现过程需要在子类中实现,如果子类的返回值是true,那么执行if中的语句,如果子类的返回值是false,那么就不再执行if中的语句,通过这种方式,子类就可以控制父类中流程的执行过程,这就是钩子方法,钩子方法都是需要在子类中实现的,因此都是抽象方法,并且一般以is-或者do-的方式命名。
优缺点
优点
模板方法模式把固定的算法骨架或者流程固定在模板类中的模板方法中,去除了子类中的重复代码;
在具体的子类中实现算法的具体实现,有助于扩展;
扩展子类时不需要修改原有模板类的代码,符合开闭原则;
缺点
每个具体的实现都需要添加一个新的子类,这会导致类的个数增加,设计更加抽象;
适用场景
模板方法模式适用于在一批子类的功能中可以提取出公共的算法骨架或者事件流程,将公共的部分放到模板类中,在子类中只留下具体的实现。
总结
模板方法模式在基类中定义了公共的部分,在子类中实现具体的细节,扩展时并不需要修改原有代码,符合开闭原则,但是在各个子类中都存在各自的特性,因此是破坏了里式替换原则,模板方法模式是一个行为型设计模式,是否选择这个模式取决了你的算法骨架或者说事件流程是否固定,如果固定了就可以在子类中实现具体的算法细节。