1.定义
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类能够在不改变算法结构的情况下,重新定义算法中的某些步骤。
2.模式特点
2.1.模式中的几个特点
此模式需要有个模板类(抽象类)来定义算法的主体结构,此结构中每一步骤则有子类来提供。模板类中的几个特点如下:
- 模板方法
定义了整体步骤的方法,通常设置为final类型,防止子类重写。 - 原语操作
需要设置为抽象类型的方法,即需要子类来提供实现的方法。 - 钩子方法
由主体结构中通过的一些方法,由模板类提供缺省实现,可以由子类选择是否重写的方法。
2.2.类图
2.3.好莱坞原则
定义:别调用我们,我们会调用你。
此原则之下,我们允许底层组件将自己挂钩到系统上,但是高层组件会决定时候以及用什么方式来调用这些低层组件。
好莱坞原则与依赖倒置原则区别:
- 依赖倒置原则:让我们尽量避免使用具体类,多使用抽象。
- 好莱坞原则:是用在创建框架或者组件上的一种技巧,能够让低层组件挂钩到系统中,又不会让高层组件依赖低层组件。
- 两者的目标都是为了解耦,但是依赖倒置原则更加注重在设计中避免依赖。
3.测试代码
模板类
/**
* 模板类
* 模板方法定义为final,禁止子类覆盖
* init、destory为钩子方法,子类可以选择是否重写者两个方法来达到自己的目的
*/
public abstract class AbstractClass {
final void execute() {
init();
run();
destory();
}
void init() {
System.out.println("init...");
}
abstract void run();
void destory() {
System.out.println("destory...");
}
}
具体实现类(app)
/**
* app类实现自己的run方法
*/
public class AppClass extends AbstractClass {
@Override
void run() {
System.out.println("learn course...");
}
}
具体实现类(game)
/**
* game类实现自己的run方法
* 并且使用钩子方法destory来达到在游戏销毁前保存游戏信息
*/
public class GameClass extends AbstractClass {
@Override
void run() {
System.out.println("play game....");
}
@Override
void destory() {
System.out.println("save game info...");
super.destory();
}
}
测试入口
public class InitMain {
public static void main(String[] args) {
GameClass game = new GameClass();
game.execute();
AppClass app = new AppClass();
app.execute();
}
}
输出如下:
init…
play game….
save game info…
destory…
init…
learn course…
destory…
4.总结
模板方法为我们提供了一种代码服用的重要技巧,可以将流程相似的算法或者流程统一由超类提供,将具体实现由子类提供,并且提供钩子方法,可以让子类是否重写来实现流程的一些特殊控制。
优点:
- 公共代码只存在于一个地方,方便维护。
- 模板方法提供了一个框架,新加入的子类只需要实现自己的方法即可。
- 行为由父类控制,具体实现则有子类提供。
缺点:
- 如果算法步骤需要修改(添加或删除步骤),则需要修改所有的子类。
- 类的组织方式没有弹性,如果新加入一个子类,则需要重写所有的抽象方法。
- 每一个不同实现都需要一个子类,导致类过多系统更加庞大。