本文要解决的几个问题,
1、什么是模板方法模式;
2、模板方法模式的使用场景;
3、模板方法模式的优点;
4、源码中有哪些地方使用到了模板方法模式;
带着这几个问题,我们开始今天的设计模式的分享。
一、模式入场
大家在日常的工作生活中肯定碰到过这样的场景,比如,你要转正答辩了,总要有个PPT吧,这时你是不是会问你同事要个述职的PPT模板,有个模板的好处这里自不用说。你去帮助单位去投标拿项目了,你是不是要问甲方爸爸要个模板,按照模板准备你的材料。生活中这样的例子太多了,有模板好办事。
在平时的开发过程中,不知道你是否碰到过类似的情形,你要调用系统A和系统B的接口,把系统A和系统B的数据读取过来,经过处理存储到自己的数据库里。
针对这样的场景你要怎么设计呐,首先,针对这样一个场景进行分析,要明确的是需要调用两个系统的接口,这两个系统返回的数据是不一样的,并且要存储到不同的表中,下面先试图实现下这个场景。有两个类SyncSystemA和SyncSystemB分别表示处理系统A和系统B的接口数据,
SyncSystemA.java
package com.example.template;
public class SyncSystemA {
public void syncData(){
//1、组装参数
String url="http://a.com/query";
String param="A";
//2、发送请求
String result=sendRequest(url,param);
//3、解析
String result2=parse(result);
//4、保存数据
saveData(result2);
}
private String sendRequest(String url,String param){
System.out.println("发送请求到A");
return "";
}
private String parse(String result){
System.out.println("对A返回结果进行解析");
return "";
}
private void saveData(String result){
System.out.println("保存A的数据");
}
}
SyncSystemB.java
package com.example.template;
public class SyncSystemB {
public void syncData(){
//1、组装参数
String url="http://b.com/query";
String param="A";
//2、发送请求
String result=sendRequest(url,param);
//3、解析
String result2=parse(result);
//4、保存数据
saveData(result2);
}
private String sendRequest(String url,String param){
System.out.println("发送请求到B");
return "";
}
private String parse(String result){
System.out.println("对B的返回结果进行解析");
return "";
}
private void saveData(String result){
System.out.println("保存B的数据");
}
}
下面看测试方法,Test.java
package com.example.template;
public class Test {
public static void main(String[] args) {
SyncSystemA syncSystemA=new SyncSystemA();
SyncSystemB syncSystemB=new SyncSystemB();
syncSystemA.syncData();
System.out.println("-----------");
syncSystemB.syncData();
}
}
返回结果如下,
发送请求到A
对A返回结果进行解析
保存A的数据
组装发送到系统B的参数
发送请求
解析系统B的返回结果
保存数据
Process finished with exit code 0
看到上面的结果同样实现了功能,而且从代码风格上是不是更简洁,而且使用到了模板方法模式。
看下《Head First 设计模式》一书中给模板方法模式下的定义
模板方法模式在一个方法中 定义一个算法的骨架,而 将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下, 重新定义算法中的某些步骤。
上面的释义定义的太完美了,多读几遍上面的释义和我们上面的AbstractSyncData类对比下
算法的骨架对应syncData方法
一些步骤延迟到子类对应assembleParam和parse方法
重新定义算法中的某些步骤对应assembleParam和parse方法,因为针对不同的实现有不同的处理逻辑。
模板方法的使用场景上面已经提到过, 在开发中要善于抽象,把一个场景中的步骤抽象成不同的几步,如果有多种实现,那么此时便是使用模板方法的大好时机。
番外
想多说一句的是,现在不是都谈面向接口编程,那么针对面向接口编程我们要如何改造上面的模板方法模式呐,只需要把syncData放到接口中即可,
package com.example.template;
public interface SyncData {
//同步数据
void syncData();
}
相应的抽象类实现该接口即可,
其UML图如下,
三、追寻源码
上面已经系统的学习了模板方法模式,下面看下在源码中的使用,
1、mybatis的BaseExecutor
在mybatis的BaseExecutor类中有update方法,
该方法来自于接口Executor,该方法又调用了doUpdate方法,该方法在BaseExecutor中是抽象方法,
看下实现的子类,
和我们上面的例子是不是很像,或者说就是同一个,再看下其uml
2、spring的AbstractApplicationContext
在spring的AbstractApplicaitonContext类中有fresh()方法,该方法中调用了obtainFreshBeanFactory方法,
obtainFreshBeanFactory方法,
看下这两个方法,
这两个方法是抽象的,肯定也是模板方法了。
四、总结
模板方法模式的精髓在于抽象,抽象出完成某个功能的步骤,再把个性化的步骤做为抽象方法,让子类延迟实现,公有的方法在抽象类中完成。在使用模板方法时由于存在抽象类,会出现多个继承子类的情况,需要视情况而定。另外,模板方法模式可以结合接口使用,实现面向接口编程。
首发于:https://www.toutiao.com/article/7097584508639183367/
Original: https://www.cnblogs.com/teach/p/16271356.html
Author: 良工说技术
Title: 源码中的设计模式–模板方法模式
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/594185/
转载文章受原作者版权保护。转载请注明原作者出处!