Java设计模式-模板模式
一、概述
模板模式(Template Pattern)是一种行为型设计模式,通过定义算法骨架并允许子类重写特定步骤,实现代码复用与扩展。其核心在于控制**流程标准化**,同时保留关键环节的灵活性。
没办法向小白从浅到深来解读,必须深入浅出来理解这个东西(骗你的🫢)。
ps.非要讲简单—> 依然是跟策略模式篇(我前一篇文章)一样的思路
用电饭煲煮米🍚,可以设计一个标准流程[这个标准流程就是上面说到的算法骨架]。
标准流程 : 取米=>淘米=>装锅=>插电=>按电饭煲按键煮饭;
那怎么允许代发复用可扩展?给你默认的一种模式,你可以自定义实现其方法来得到你想要的。
abstract void 取米 ,重写=> 取小米/大米/黑米/糯米;
abstract void 装锅, 重写=>加一指节水煮饭/加两指节水煮粥;
abstract void 按电饭煲按键煮饭,重写 => 快煮/精煮/慢煮/ 大火/中火/小火
如果到这还不会也不着急,多看多写!
1.1 核心组件
-
抽象模板类(Abstract Template):定义算法框架(电饭煲煮米整个流程)和可重写的步骤方法 (中间可以自定义扩展的步骤)
-
具体子类(Concrete Class):实现父类定义的抽象方法,完成特定业务逻辑 (实现电饭煲煮小米粥模板)
-
钩子方法(Hook Method) :提供默认实现的可选扩展点 ,(粮仓取米 => 提供多种取米选择)
1.2 模式优势
-
避免重复代码:将公共逻辑提升到父类
-
增强扩展性:子类只需关注差异化实现
-
符合开闭原则:新增请求类型无需修改父类逻辑
二、模板模式应用场景
ps.简单的结束了 => 一定要去试试读Spring源码,RestTemplate
,当然这其中只是引用了模版模式思想,不完全契合本文的模版模式的代码格式,并不是我说的不对或者Spring写的不对,而是模版模式的精髓就在于前面标红的流程标准化,他把可扩展的部分放在了整个http请求实例的构件上。有兴趣的就搜搜向关的文档。
2.1 典型使用场景
-
业务流程标准化 如HTTP请求处理、文件解析、事务管理等需要固定流程的场景
-
框架扩展点设计 如Spring的
JdbcTemplate
、RestTemplate
等模板类 -
多版本实现共存 如不同协议(HTTP/HTTPS)或数据格式(JSON/XML)的处理
2.2 设计原则
当多个类有相同流程但不同实现细节时优先采用
模板方法建议声明为final
防止子类破坏流程结构
三、RestTemplate中的模板模式实践
3.1 Spring RestTemplate类结构
3.2 具体实现示例
// 抽象模板方法定义(伪代码)
public abstract class HttpRequestTemplate {
// 模板方法(定义处理流程)
public final ResponseEntity<String> execute(String url) {
validateUrl(url);
ClientHttpRequest request = createRequest(url);
customizeHeaders(request.getHeaders());
logRequest(request);
return executeRequest(request);
}
// 抽象步骤(子类必须实现)
protected abstract ClientHttpRequest createRequest(String url);
// 默认实现(子类可重写)
protected void customizeHeaders(HttpHeaders headers) {
headers.add("User-Agent", "TemplatePatternDemo/1.0");
}
// 钩子方法(子类可选重写)
protected void logRequest(ClientHttpRequest request) {
System.out.println("Sending request to: " + request.getURI());
}
}
// GET请求实现
public class GetRequestTemplate extends HttpRequestTemplate {
@Override
protected ClientHttpRequest createRequest(String url) {
return new ClientHttpRequest(url, HttpMethod.GET);
}
}
// POST请求实现
public class PostRequestTemplate extends HttpRequestTemplate {
@Override
protected ClientHttpRequest createRequest(String url) {
ClientHttpRequest request = new ClientHttpRequest(url, HttpMethod.POST);
request.getBody().write("template=pattern".getBytes());
return request;
}
@Override
protected void customizeHeaders(HttpHeaders headers) {
super.customizeHeaders(headers);
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
}
}
3.3 Spring源码衔接
实际RestTemplate
通过ClientHttpRequestFactory
接口实现模板模式:
// 模板方法调用链
restTemplate.exchange()
-> ClientHttpRequestFactory.createRequest()
-> BufferingClientHttpRequestWrapper.executeInternal()
-> AbstractClientHttpRequest.execute()
3.4 模式实现对比
设计要素 | RestTemplate实现 | 标准模板模式 |
---|---|---|
模板方法 | execute() 方法 | 自定义的process() 方法 |
可变步骤 | ClientHttpRequest 创建过程 | 抽象方法doExecute() |
扩展机制 | 通过RequestCallback 接口 | 子类重写父类方法 |
四、扩展与最佳实践
4.1 扩展优化建议
- 与Spring集成
使用@Primary
注解指定默认模板实现 - 动态选择模板
结合策略模式实现运行时模板切换(如根据QPS选择同步/异步模板) - 钩子方法增强
添加preExecute()
和postExecute()
生命周期钩子
4.2 线程池扩展示例
这块水一下内容,纯偷懒写法,自己在项目中千万不要new这种线程池,小心被开除😂。
public class AsyncRestTemplate extends HttpRequestTemplate {
private ExecutorService threadPool = Executors.newFixedThreadPool(8);
@Override
public final ResponseEntity<String> execute(String url) {
return threadPool.submit(() -> super.execute(url)).get();
}
}
通过模板模式,RestTemplate实现了请求处理标准化与协议扩展灵活性的平衡。完整案例可参考Spring框架源码中的RestTemplate
与JdbcTemplate
实现。