论模板模式
模板方法模式的实现方案比对
问题:模板方法模式的主要意义在于规范算法流程。标准的模板方法模式采用抽象类的实现方案。但规范流程更像是规范行为。而抽象类与接口相比,抽象类侧重于属性,接口侧重于行为。再者java8开始,接口中可以编写默认方法,因此模板方法模式可以采用抽象类和接口两种实现方案。那么到底哪种实现方案比较合适呢?
需求:按指定流程推送数据。流程如下:
从数据库中查询数据 ---> 封装数据 ---> 推送
标准模板方法模式的写法
抽象模板类(抽象类):规范数据的使用流程
/**
* Created by r.x on 2019/4/5.
* 抽象模板
*/
public abstract class Template {/**
* 数据使用流程:
* 1、查库
* 2、封装数据
* 3、推送数据
*/
public final void use() {
List list = queryDb();
JSONObject json = packData(list);
push(json);
}/**
* 从数据库查询数据
*
* @return
*/
protected abstract List queryDb();
/**
* 按要求 封装数据
*
* @param list
* @return
*/
protected abstract JSONObject packData(List list);
/**
* 通用的数据推送方法
* @param json
*/
private void push(JSONObject json) {
System.out.println(json);
}
}
string的具体使用实现
/**
* Created by r.x on 2019/4/5.
* string的具体使用实现
*/
public class PushString extends Template {@Override
protected List queryDb() {
return Collections.singletonList("string");
}@Override
protected JSONObject packData(List list) {
StringJoiner joiner = new StringJoiner(",");
list.forEach(joiner::add);
JSONObject json = new JSONObject();
json.put("type", "string");
json.put("data", joiner.toString());
return json;
}
}
integer的具体使用实现
/**
* Created by r.x on 2019/4/5.
* integer的具体使用实现
*/
public class PushInteger extends Template {@Override
protected List queryDb() {
return Collections.singletonList(0);
}@Override
protected JSONObject packData(List list) {
JSONObject json = new JSONObject();
json.put("type", "integer");
json.put("data", list);
return json;
}
}
入口类:
/**
* Created by r.x on 2019/4/5.
* 入口类
*/
public class Demo {public static void main(String[] args) {
Template pushString = new PushString();
pushString.use();
Template pushInteger = new PushInteger();
pushInteger.use();
}
}
输出结果
{"data":"string","type":"string"}
{"data":[0],"type":"integer"}
用接口的方式实现模板方法模式
抽象模板(接口)
/**
* Created by r.x on 2019/4/5.
* 抽象模板
*/
public interface ITemplate {
/**
* 数据使用流程:
* 1、查库
* 2、封装数据
* 3、推送数据
*/
default void use() {
List list = queryDb();
JSONObject json = packData(list);
push(json);
}/**
* 从数据库查询数据
*
* @return
*/
List queryDb();
/**
* 按要求 封装数据
*
* @param list
* @return
*/
JSONObject packData(List list);
/**
* 通用的数据推送方法
* @param json
*/
default void push(JSONObject json) {
System.out.println(json);
}
}
integer的具体使用实现
/**
* Created by r.x on 2019/4/5.
* integer的具体使用实现
*/
public class PushIntegerImpl implements ITemplate {@Override
public List queryDb() {
return Collections.singletonList(-1);
}@Override
public JSONObject packData(List list) {
JSONObject json = new JSONObject();
json.put("type", "integer impl");
json.put("data", list);
return json;
}
}
string的具体使用实现
/**
* Created by r.x on 2019/4/6.
* string的具体使用实现
*/
public class PushStringImpl implements ITemplate {
@Override
public List queryDb() {
return Collections.singletonList("string impl");
}@Override
public JSONObject packData(List list) {
StringJoiner joiner = new StringJoiner(",");
list.forEach(joiner::add);
JSONObject json = new JSONObject();
json.put("type", "string impl");
json.put("data", joiner.toString());
return json;
}
}
入口类
/**
* Created by r.x on 2019/4/5.
* 入口类
*/
public class DemoImpl {public static void main(String[] args) {
ITemplate pushString = new PushStringImpl();
pushString.use();
ITemplate pushInteger = new PushIntegerImpl();
pushInteger.use();
}
}
输出结果:
{"data":"string impl","type":"string impl"}
{"data":[-1],"type":"integer impl"}
那么从输出结果可以看出,采用接口的方式也是可以实现同样的效果的
抽象类与接口方案的比对
【论模板模式】从以上对比可以看出,虽然接口方式也能实现模板方法模式,但接口中定义的方法完全暴露了,甚至连最重要的use()方法也被暴露了,因为子类可以覆盖接口中的默认方法,此时就失去了规范流程的意义了。因此,即使技术上可行,但也不推荐使用接口的实现方案。
推荐阅读
- opencv|opencv C++模板匹配的简单实现
- 试论化院的学生自组织
- 不以胜负论出关
- 论刘备的成功之道
- 概率论/统计学|随机变量 的 分布函数 与 概率密度函数 的区别
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- 二论鲲鹏(夜话庄子2)
- 无论你是谁,都有两件事,无法掌控
- web网页模板|如此优秀的JS轮播图,写完老师都沉默了
- --木木--|--木木-- 第二课作业#翼丰会(每日一淘6+1实战裂变被动引流# 6+1模式)