1.为什么会有模板方法模式?
当我们编写程序时,肯定会遇到一个相同处理逻辑的方法被多个子类调用的场景,这种重复造轮子的冗余代码使得整个代码结构复杂冗长,又或者为处理相似的业务而设计多个算法其流程又是无太大差别的,这时候为了程序整体架构的简洁性,可以将这些大部分步骤相同且重复而个别步骤在实现时可能不同的代码考虑使用模板方法模式处理。
定义:
定义一个操作中的算法的框架, 而将一些步骤延迟到子类中。 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤一个抽象类公开定义了执行它的方法的方式/模板。
模板模式就像站在巨人的肩膀上,在大方向上借鉴别人的经验,进行适当的调整,以满足我们自己定制化的需求。当我们不具备造轮子的能力的时候,合理选择适合的模板也是一种不错的选择。
2.使用场景
- 一些方法通用,并且逻辑基本相同,却在每一个子类都重新写了这一方法,可以将这些方法抽取出来放到一个模板抽象类中。
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现
- 重构时,模板方法是一个经常使用的方法,把相同的代码抽取到父类中,然后通过构造函数约束其行为
- 程序主框架相同,细节不同的情况下,也可以使用模板方法
- 当要完成在某个过程,该过程要执行一系列步骤 ,这一系列的步骤基本相同,但其个别步骤在实现时可能不同,通常考虑用模板方法模式来处理
3.二要素
- 抽象类:定义了算法框架的基本执行流程
- 具体子类:执行流程中的具体实现细节交由各个子类实现
4.模板方法设计
我们通过下面的实例来演示模板方法模式的使用。
创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写(防止恶意操作)。Cricket 和 Football 是扩展了 Game 的实体类,它们重写了抽象类的方法,具体的游戏规则交给子类决定。
模板方法UML图:
Game
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//模板
public final void play(){
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
Cricket
public class Cricket extends Game {
@Override
void endPlay() {
System.out.println("Cricket Game Finished!");
}
@Override
void initialize() {
System.out.println("Cricket Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the game!");
}
}
Football
public class Football extends Game {
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}
@Override
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
}
测试
public class TemplatePatternDemo {
public static void main(String[] args) {
Game game = new Cricket();
game.play();
System.out.println();
game = new Football();
game.play();
}
}