模板方法模式在项目中的实际使用

一、基本描述

1,基本思想:在一个抽象类中公开定义了执行它的方法的模板,它的子类可以按需重写方法的实现,但调用将以抽象类中定义的方式进行。算法只存在于父类中,容易修改,需要修改算法的时候,只需要修改父类的模板方法或者已经实现的步骤,子类就会继承这些修改

2,实现了最大化的代码复用:父类的模板方法和已经实现的步骤会被继承直接使用

3,即统一了算法,又提供了很大的灵活性:父类模板方法确保了算法的结构不变,同时由子类提供部分步骤的实现

4,不足之处:每一个不同的实现都需要不同的子类去实现,导致类的数量增加,系统将变得庞大

5,注意事项:定义的模板方法为final方法,不让子类覆盖

6,使用场景:当要完成某个过程,这个过程需要执行一系列的步骤,这些步骤基本相同,但是其中个别的步骤可能不同,这时就可以使用模板方法模式

二、代码实战

业务场景描述

xxx数据局需要做数据的归集,需要各个业务系统,增量同步自己的数据到数据中心。

代码

SyncTemplate.java

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.converge.entity.SyncLatestId;
import com.converge.entity.SyncRecord;
import com.converge.mapper.SyncLatestIdMapper;
import com.converge.mapper.SyncRecordMapper;
import com.converge.util.SpringContextUtil;
import com.converge.util.WebServiceUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author sunweidong
 */
public abstract class SyncTemplate {

    private static final Object objLock = new Object();

    private SyncLatestIdMapper syncLatestIdMapper;

    private SyncRecordMapper syncRecordMapper;

    /**
     * 推送数据
     */
    public final <T> void pushData() {
        // 查询最近一次同步的表的数据
        Integer id = findLatestId();
        // 查询表数据信息
        List<T> data = findDataById(id);
        // 过滤组装文件生成新的List<Map<String, String>>结构
        List<Map<String, String>> list = WebServiceUtil.processList(data);
        if (list != null && list.size() > 0) {
            // 生成xml文件
            String xml = WebServiceUtil.generateXML(list);
            // 推送数据并得到最近一次推送的数据的ID
            Object[] obj = WebServiceUtil.push("", xml);
            // 保存同步结果的信息:原始数据的ID,返回的结果,表的名称
            saveSyncRecord(getIds(list), obj);
            // TODO (author:sunweidong) 判断返回结果的有效性
            if (false) {
                // 保存最近一次同步的数据的ID
                saveLatestId((Integer) obj[0]);
            }
        }
    }

    /**
     * 查询表数据信息
     *
     * @param id 主键ID
     * @return 查询出来的表数据
     */
    protected abstract <T> List<T> findDataById(Integer id);

    /**
     * 获取表名称
     *
     * @return 表名称
     */
    protected abstract String getTableName();

    /**
     * 查询最近一次同步的表的数据
     *
     * @return 最近一次同步的数据ID
     */
    private Integer findLatestId() {
        QueryWrapper<SyncLatestId> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SyncLatestId::getTableName, getTableName());
        SyncLatestId syncLatestId = getSyncLatestIdMapper().selectOne(queryWrapper);
        return syncLatestId == null ? 0 : syncLatestId.getTableId();
    }

    /**
     * 保存最近一次同步的数据的ID
     *
     * @param id 最近一次同步的数据ID
     */
    private void saveLatestId(Integer id) {
        QueryWrapper<SyncLatestId> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SyncLatestId::getTableName, getTableName());
        SyncLatestId syncLatestId = getSyncLatestIdMapper().selectOne(queryWrapper);
        if (syncLatestId == null) {
            syncLatestId = new SyncLatestId();
            syncLatestId.setTableName(getTableName());
            syncLatestId.setTableId(id);
            getSyncLatestIdMapper().insert(syncLatestId);
        } else {
            syncLatestId.setTableId(id);
            getSyncLatestIdMapper().updateById(syncLatestId);
        }
    }

    /**
     * 保存同步结果的信息:原始数据的ID,返回的结果,表的名称
     *
     * @param ids 原始数据的ID
     * @param obj 执行推送返回的结果
     */
    private void saveSyncRecord(List<String> ids, Object[] obj) {
        SyncRecord syncRecord = new SyncRecord();
        syncRecord.setTableName(getTableName());
        syncRecord.setContent(JSON.toJSONString(ids));
        syncRecord.setRespMsg(JSON.toJSONString(obj));
        syncRecord.setCreateTime(new Date());
        getSyncRecordMapper().insert(syncRecord);
    }

    /**
     * 获取发送数据的全部ID
     */
    private List<String> getIds(List<Map<String, String>> list) {
        List<String> ids = new ArrayList<>();
        list.stream().forEach(v -> ids.add(v.get("id")));
        return ids;
    }

    private SyncLatestIdMapper getSyncLatestIdMapper() {
        if (syncLatestIdMapper == null) {
            synchronized (objLock) {
                if (syncLatestIdMapper == null) {
                    syncLatestIdMapper = SpringContextUtil.getBean(SyncLatestIdMapper.class);
                }
            }
        }
        return syncLatestIdMapper;
    }

    private SyncRecordMapper getSyncRecordMapper() {
        if (syncRecordMapper == null) {
            synchronized (objLock) {
                if (syncRecordMapper == null) {
                    syncRecordMapper = SpringContextUtil.getBean(SyncRecordMapper.class);
                }
            }
        }
        return syncRecordMapper;
    }
}

ScheduleTask.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * @author sunweidong
 */
@Component
@EnableScheduling
public class ScheduleTask {

    private CaseCurrentServiceImpl caseCurrentService;

    @Autowired
    ScheduleTask(CaseCurrentServiceImpl caseCurrentService) {
        this.caseCurrentService = caseCurrentService;
    }

    @Scheduled(fixedRate = 60 * 1000)
    public void minuteTask() {
        caseCurrentService.pushData();
    }
}

CaseCurrentServiceImpl.java

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.converge.entity.CaseCurrent;
import com.converge.mapper.CaseCurrentMapper;
import com.converge.service.SyncTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 当前流转案件(CaseCurrent)表服务实现类
 *
 * @author sunweidong
 * @createTime 2021-03-11
 */
@Service("caseCurrentService")
@Slf4j
public class CaseCurrentServiceImpl extends SyncTemplate {

    @Autowired
    private CaseCurrentMapper caseCurrentMapper;

    @Override
    protected List<CaseCurrent> findDataById(Integer id) {
        QueryWrapper<CaseCurrent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().ge(CaseCurrent::getId, id);
        return caseCurrentMapper.selectList(queryWrapper);
    }

    @Override
    protected String getTableName() {
        return "case_current";
    }
}

友情提示,以下工具类可以在我的博客找到。

  • SpringContextUtil.java
  • ReflectPojoUtil.java
  • SimpleDateFormatUtil.java
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值