设计模式之模板方法模式(三分钟学会一个设计模式)

模板方法模式(Template Method Pattern)也称之为模板模式(Template Pattern),是设计模式中最简单的模式之一。

先来看定义:
定义一个操作中算法的骨架(模板),将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重新定义算法某些特定的步骤。
这个定义还是有一些晦涩,我的理解是这样的:(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )
在父类中我们可以定义一块业务的整体实现过程,但是针对某些步骤的具体实现逻辑,我们可以暂时先只定义一个抽象方法,在未来定义子类的过程中,实现/重写该方法。
这个模式主要是为了解决,很多场景中,我们并不知道未来实际使用中,具体需要怎么实现,甚至会出现多个具体实现,针对此,我们可以先定义父类中已经明确的业务。
大致的调用结构如下:

它是面向对象的23种设计模式中的一种,属于行为模式的范围。
来看示例代码:

音乐播放器抽象类

 1 package com.example.demo.learn.pattern.behavior.templatemethod;
 2 
 3 import lombok.extern.slf4j.Slf4j;
 4 
 5 /**
 6  * @discription
 7  */
 8 @Slf4j
 9 public abstract class AbstractMusicPlayer {
10     public void startUp() {
11         showFrame();
12         doCustomizedOpt();
13     }
14 
15     protected abstract void playWelcomeMsg();
16 
17     protected void showFrame() {
18         showMainFrame();
19         playWelcomeMsg();
20     }
21 
22     protected abstract void doCustomizedOpt();
23 
24 
25     protected abstract void showMainFrame();
26 }

酷猫播放器

 1 package com.example.demo.learn.pattern.behavior.templatemethod;
 2 
 3 import lombok.extern.slf4j.Slf4j;
 4 
 5 /**
 6  * @discription
 7  */
 8 @Slf4j
 9 public class CoolCatPlayer extends AbstractMusicPlayer{
10     @Override
11     protected void playWelcomeMsg() {
12       log.warn("hi man");
13     }
14 
15     @Override
16     protected void doCustomizedOpt() {
17         log.warn("您有一份价值99元的免费礼品待领取,快点击下方链接");
18     }
19 
20     @Override
21     protected void showMainFrame() {
22         log.warn("打开酷猫音乐主界面");
23     }
24 }

酷他音乐盒

 1 package com.example.demo.learn.pattern.behavior.templatemethod;
 2 
 3 import lombok.extern.slf4j.Slf4j;
 4 
 5 /**
 6  * @discription
 7  */
 8 @Slf4j
 9 public class CoolHePlayer extends AbstractMusicPlayer {
10     @Override
11     protected void playWelcomeMsg() {
12         log.warn("欢迎来到酷他音乐盒");
13     }
14 
15     @Override
16     protected void doCustomizedOpt() {
17         log.warn("一刀999,和兄弟一起战个痛快");
18     }
19 
20     @Override
21     protected void showMainFrame() {
22         log.warn("打开酷他音乐盒主界面");
23     }
24 }

执行主类

 1 package com.example.demo.learn.pattern.behavior.templatemethod;
 2 
 3 /**
 4  * @discription
 5  */
 6 
 7 public class PatternMain {
 8     public static void main(String[] args) {
 9         AbstractMusicPlayer coolCat = new CoolCatPlayer();
10         coolCat.startUp();
11 
12         AbstractMusicPlayer coolHe = new CoolHePlayer();
13         coolHe.startUp();
14     }
15 }

输出如下

15:38:12.515 [main] WARN com.example.demo.learn.pattern.behavior.templatemethod.CoolCatPlayer - 打开酷猫音乐主界面
15:38:12.518 [main] WARN com.example.demo.learn.pattern.behavior.templatemethod.CoolCatPlayer - hi man
15:38:12.518 [main] WARN com.example.demo.learn.pattern.behavior.templatemethod.CoolCatPlayer - 您有一份价值99元的免费礼品待领取,快点击下方链接
15:38:12.518 [main] WARN com.example.demo.learn.pattern.behavior.templatemethod.CoolHePlayer - 打开酷他音乐盒主界面
15:38:12.518 [main] WARN com.example.demo.learn.pattern.behavior.templatemethod.CoolHePlayer - 欢迎来到酷他音乐盒
15:38:12.518 [main] WARN com.example.demo.learn.pattern.behavior.templatemethod.CoolHePlayer - 一刀999,和兄弟一起战个痛快

我们定义了一个播放器的类,并且约定了播放器启动时,我们需要具体做的业务:

类图

步骤1、打开主界面

步骤2、做一些定制的用户操作
但是有多个播放器(如酷猫音乐、酷他音乐盒),他们的主界面和用户定制操作都各有不同,因此我们可以先只定义以上操作的抽象方法,对于具体操作的实现留给子类完成即可。

模板方法核心的步骤就是2点:
父类中定义骨架(模板),组织各种定义好的抽象方法
子类根据实际业务实现抽象方法