0%

初学 Java 设计模式(二十二):实战模板方法模式 「开发必备利器 uTools」

一、模板方法模式介绍

1. 解决的问题

主要解决在多个子类中重复写某个通用方法的问题。

2. 定义

模板方法模式是一种行为设计模式,它在超类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。

3. 应用场景

  • 当只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时,可使用模板方法模式。
  • 当多个类的算法除一些细微不同之外几乎完全一样时,可使用模板方法模式。但后果是:只要算法发生变化,可能要修改所有的类。

二、模板方法模式优缺点

1. 优点

  • 可以仅允许客户端重写一个大型算法中的特定部分,使得算法的其他部分修改对其所造成的影响减小。
  • 可以将重复代码提取到一个超类中。

2. 缺点

  • 部分客户端可能会受到算法框架的限制。
  • 通过子类抑制默认步骤实现可能会导致违反里氏替换原则
  • 模板方法中的步骤越多,其维护工作就可能越困难。

三、模板方法模式应用实例:开发必备利器 uTools

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();

/**
* 渲染翻译页面iframe
*/
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("抓取百度翻译页面");
}

/**
* 渲染翻译页面iframe
*/
@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("抓取谷歌翻译页面");
}

/**
* 渲染翻译页面iframe
*/
@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("抓取有道翻译页面");
}

/**
* 渲染翻译页面iframe
*/
@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

四、模板方法模式结构

在这里插入图片描述

  1. 抽象类(Abstract Class)会声明作为算法步骤的方体,以及依次调用它们的实际模板方法。算法步骤可以被声明为抽象类型,也可以提供一些默认实现。
  2. 具体类(Concrete Class)可以重写所有步骤,但不能重写模板方法自身。

设计模式并不难学,其本身就是多年经验提炼出的开发指导思想,关键在于多加练习,带着使用设计模式的思想去优化代码,就能构建出更合理的代码。

源码地址:https://github.com/yiyufxst/design-pattern-java

参考资料:
小博哥重学设计模式:https://github.com/fuzhengwei/itstack-demo-design
深入设计模式:https://refactoringguru.cn/design-patterns/catalog