一、模板方法模式介绍
1. 解决的问题
主要解决在多个子类中重复写某个通用方法的问题。
2. 定义
模板方法模式是一种行为设计模式,它在超类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。
3. 应用场景
- 当只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时,可使用模板方法模式。
- 当多个类的算法除一些细微不同之外几乎完全一样时,可使用模板方法模式。但后果是:只要算法发生变化,可能要修改所有的类。
二、模板方法模式优缺点
1. 优点
- 可以仅允许客户端重写一个大型算法中的特定部分,使得算法的其他部分修改对其所造成的影响减小。
- 可以将重复代码提取到一个超类中。
2. 缺点
- 部分客户端可能会受到算法框架的限制。
- 通过子类抑制默认步骤实现可能会导致违反里氏替换原则。
- 模板方法中的步骤越多,其维护工作就可能越困难。
1. 实例场景
一般来说,开发在学习和工作中都会有各种各样的小工具需求,比如 json 转换、翻译、时间转换、命令文档。
今天就给大家介绍一个私藏多年、可以将上述工具都集合在一起的大利器:uTools。
uTools 是一个极简、插件化的现代桌面软件,通过自由选配丰富的插件,打造得心应手的工具集合。

我最最最常用的就是聚合翻译了,毕竟变量命名是个大问题。
uTools 的翻译功能聚合了有道翻译、谷歌翻译、腾讯翻译,也可以切换选择更多如搜狗翻译、微软翻译等等。

今天,就以 uTools 的聚合翻译插件为例,介绍一下模板方法模式。
2. 状态模式实现
2.1 工程结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| template-pattern └─ src ├─ main │ └─ java │ └─ org.design.pattern.template │ └─ service │ ├─ TranslateService.java │ └─ impl │ ├─ BaiDuTranslateServiceImpl.java │ ├─ GoogleTranslateServiceImpl.java │ └─ YouDaoTranslateServiceImpl.java └─ test └─ java └─ org.design.pattern.template.test └─ TranslateTest.java
|
2.2 代码实现
翻译服务超类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public abstract class TranslateService {
public abstract void crawlTranslatePage();
public abstract void renderTranslateIframe();
public void provideTranslate() { crawlTranslatePage(); renderTranslateIframe(); } }
|
百度翻译服务实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
@Slf4j public class BaiDuTranslateServiceImpl extends TranslateService {
@Override public void crawlTranslatePage() { log.info("抓取百度翻译页面"); }
@Override public void renderTranslateIframe() { log.info("适配并渲染百度翻译页面"); } }
|
谷歌翻译服务实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
@Slf4j public class GoogleTranslateServiceImpl extends TranslateService {
@Override public void crawlTranslatePage() { log.info("抓取谷歌翻译页面"); }
@Override public void renderTranslateIframe() { log.info("适配并渲染谷歌翻译页面"); } }
|
有道翻译服务实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@Slf4j public class YouDaoTranslateServiceImpl extends TranslateService {
@Override public void crawlTranslatePage() { log.info("抓取有道翻译页面"); }
@Override public void renderTranslateIframe() { log.info("适配并渲染有道翻译页面"); } }
|
2.3 测试验证
2.3.1 测试验证类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
public class TranslateTest {
@Test public void test() { TranslateService baiduTranslate = new BaiDuTranslateServiceImpl(); baiduTranslate.provideTranslate(); TranslateService googleTranslate = new GoogleTranslateServiceImpl(); googleTranslate.provideTranslate(); TranslateService youDaoTranslate = new YouDaoTranslateServiceImpl(); youDaoTranslate.provideTranslate(); } }
|
2.3.2 测试结果
1 2 3 4 5 6 7 8
| 16:02:33.610 [main] INFO o.d.p.t.s.i.BaiDuTranslateServiceImpl - 抓取百度翻译页面 16:02:33.612 [main] INFO o.d.p.t.s.i.BaiDuTranslateServiceImpl - 适配并渲染百度翻译页面 16:02:33.612 [main] INFO o.d.p.t.s.i.GoogleTranslateServiceImpl - 抓取谷歌翻译页面 16:02:33.612 [main] INFO o.d.p.t.s.i.GoogleTranslateServiceImpl - 适配并渲染谷歌翻译页面 16:02:33.612 [main] INFO o.d.p.t.s.i.YouDaoTranslateServiceImpl - 抓取有道翻译页面 16:02:33.613 [main] INFO o.d.p.t.s.i.YouDaoTranslateServiceImpl - 适配并渲染有道翻译页面
Process finished with exit code 0
|
四、模板方法模式结构

- 抽象类(Abstract Class)会声明作为算法步骤的方体,以及依次调用它们的实际模板方法。算法步骤可以被声明为抽象类型,也可以提供一些默认实现。
- 具体类(Concrete Class)可以重写所有步骤,但不能重写模板方法自身。
设计模式并不难学,其本身就是多年经验提炼出的开发指导思想,关键在于多加练习,带着使用设计模式的思想去优化代码,就能构建出更合理的代码。
源码地址:https://github.com/yiyufxst/design-pattern-java
参考资料:
小博哥重学设计模式:https://github.com/fuzhengwei/itstack-demo-design
深入设计模式:https://refactoringguru.cn/design-patterns/catalog