背景: 设计一个任务系统, 任务可以有多种类型(签到,看广告,填写调查问卷 等等),每个任务的完成标准是 可以做N次。 需要记录每个任务的完成进度。每做一次需要做一些操作,如 给用户增减积分等。
设计:抽象类
@Slf4j public abstract class AbstractTaskPostProcessor { // 由子类实现。 abstract Boolean beforeProcess(UserTaskDTO userTask); // 由子类实现。 abstract Boolean process(UserTaskDTO userTask); // 由子类实现。 abstract Boolean afterProcess(UserTaskDTO userTask); /** * 上报任务后,统一的处理计算过程。 **/ public ActivityPlayerTaskVO calculate(UserTaskDTO userTask){ // 确认唯一标识符 String uid = "用户的唯一标识符"; log.info("开始任务计算,openId={}",openId); RLock lock = redissonService.getRLock("task_calculate_" + activityId + uid); try { boolean bs = lock.tryLock(); if (!bs) { log.info("任务计算中,请稍后再试"); throw new BusinessException("任务计算中,请稍后再试"); } // 处理前的特殊处理。 beforeProcess(userTask); // xxxxxx共性的操作 // 业务特殊处理 Boolean result = process(userTask); log.info("任务的处理结果:{}",result); // 处理成功更新次数 if (result) { // 处理成功的特殊处理。 afterProcess(userTask); }catch (Exception ex){ log.error("任务处理失败,原因:{}",ex); throw ex; } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } return playerTaskVO; }
根据业务类型,取子类的对象
public enum TaskActionEnum { TASK_SIGN_IN(1, "签到"), TASK_LOOK_AD(2,"看广告") } public class PostProcessorFactory { public static AbstractTaskPostProcessor getPostProcessor(TaskActionEnum action) { switch (action){ case TASK_SIGN_IN: // 签到 return SpringContextUtil.getBean(TaskSignInProcessor.class); case TASK_LOOK_AD: // 看广告 return SpringContextUtil.getBean(TaskLookAdProcessor.class); default: throw new BusinessException(GameErrorCodeEnum.ERROR_FORMAT); } } }
子类的实现:
@Service public class TaskSignInProcessor extends AbstractTaskPostProcessor{ @Autowired private IBaishiSignRecordService signRecordService; @Override public Boolean beforeProcess(UserTaskDTO userTask) { return Boolean.TRUE; } @Override public Boolean process(UserTaskDTO userTask) { return Boolean.TRUE; } @Override public Boolean afterProcess(UserTaskDTO userTask) { return Boolean.TRUE; } }
调用的入口:
public ApiResult report(UserTaskDTO userTask){ ActivityPlayerTaskVO playerTask = PostProcessorFactory.getPostProcessor(userTask.getAction()).calculate(userTask); return ApiResult.success(playerTask); }