需求
平时工作中,我们会有不少地方会使用到模板方法模式。它既可以简化们的代码,也可以规范我们的代码逻辑、约束我们的编码范围。是一个面向接口编程的好例子.
来看看我们的例子,主要场景以网管监控系统补偿数据场景来展开。简单看下spec
1、A系统监控B、C系统,B、C系统分别有BBiz与CBiz的业务
2、B、C系统通过kafka上报配置,状态,告警变更给A系统
3、A系统更新业务数据,并分析告警,状态等通知给平台其它系统
4、步骤2可能出现各种各样的问题,B、C系统可能有问题没有发出消息,A系统可能有问题没有消费消息。每天A系统会定时与B、C系统对比数据,并以B、C系统数据为准更新A系统数据
依赖设计
代码实现
1、A系统监控B、C系统,B、C系统分别有BBiz与CBiz的业务
public class BBiz {
}
public class CBiz {
}
public class BPo {
}
public class CPo {
}
2、B、C系统通过kafka上报配置,状态,告警变更给A系统
@Component
public class TopicBSubscriber {
@Autowired
private AbstractMessageBiz<BBiz, BPo> messageBiz;
public void onListener(List<Record> list) {
for (Record r : list) {
BBiz biz = convert(r);
messageBiz.update(biz);
}
}
}
@Component
public class TopicCSubscriber {
@Autowired
private AbstractMessageBiz<CBiz, CPo> messageBiz;
public void onListener(List<Record> list) {
for (Record r : list) {
CBiz biz = convert(r);
messageBiz.update(biz);
}
}
}
3、A系统更新业务数据,并分析告警,状态等通知给平台其它系统
这里使用模板方法模式来处理数据源,并好了存库通知三方系统等一系列操作
/**
*
* @param <T> 消息模型
* @param <D> 数据库模型
*/
public abstract class AbstractMessageBiz<T, D> {
public void update(T msg) {
D bizInDb = queryFormDb(msg);
D bizInMsg = convert(msg);
updateDb(bizInMsg, bizInDb);
List<Alarm> alarms = generateAlarms(bizInMsg, bizInDb);
for (Alarm a : alarms) {
// 这里可以是一个监听器
// 1、监听到告警,则发送到告警平台
// 2、告警本地落库
// 3、分析告警最高级别,关联到业务上
}
}
protected abstract D convert(T t);
/**
* 根据变化的属性
* @param forUpdate
* @return
*/
protected abstract List<Alarm> generateAlarms(D forUpdate, D inDb);
/**
* 从数据库查相关消息
*
* @param t 消息
* @return 数据库模型
*/
protected abstract D queryFormDb(T t);
/**
* 存库
* @param bizInMsg
* @param d 业务
*/
protected abstract void updateDb(D bizInMsg, D d);
}
public class BBizConsumer extends AbstractMessageBiz<BBiz, BPo> {
}
public class CBizConsumer extends AbstractMessageBiz<CBiz, CPo> {
}
4、定时check
主要是这个private List<AbstractBizCheck<?, ?>> bizCheckers;可以直接依赖。
这里C没有实现BizCheck功能,即不需要对数据进行补偿。
如果后续需要对C进行check功能,仅需要新增文件
public class CBizChecker extends AbstractBizCheck<CBiz, CPo> 即可
@Component
public class CheckJob {
@Autowired
private List<AbstractBizCheck<?, ?>> bizCheckers;
/**
* 定时任务调用
*/
public void onCheck() {
for (AbstractBizCheck<?, ?> checker : bizCheckers) {
checker.check();
}
}
}
public abstract class AbstractBizCheck<T, D> {
@Autowired
AbstractMessageBiz<T, D> messageBiz;
public void check() {
List<T> ts = queryAll();
for (T t : ts) {
messageBiz.update(t);
}
}
protected abstract List<T> queryAll();
}
@Component
public class BBizChecker extends AbstractBizCheck<BBiz, BPo> {
@Override
List<BBiz> queryAll() {
return new ArrayList<>();
}
}