模板模式实战,采用泛型+函数式+策略封装mybatis的IService的方法,进行关联表操作

模板模式

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
如何解决:将这些通用算法抽象出来。
关键代码:在抽象类实现,其他步骤在子类实现。
需求: 多个资源设计表,关联多个资源,重复操作
表结构

CREATE TABLE `materials` (
  `id` bigint(20) NOT NULL COMMENT '主键id',
  `title` varchar(255) DEFAULT NULL COMMENT '标题',
  `task` varchar(255) DEFAULT NULL COMMENT '适用课题',
  `scope` tinyint(4) DEFAULT NULL COMMENT '共享范围 0 自己 1 公开',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='教学资源信息表';



CREATE TABLE `files` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `resource_id` bigint(20) DEFAULT NULL COMMENT '资源id',
  `resource_url` varchar(255) DEFAULT NULL COMMENT '资源地址',
  `resource_name` varchar(32) DEFAULT NULL COMMENT '资源名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='文件表';

函数接口

/**
 * 资源函数
 *
 * @author bai
 * @date 2022/10/05
 */
@FunctionalInterface
public interface ResourceFunc<E, F extends FilesEntity> {

    /**
     * 应用
     *
     * @param list 列表
     * @param b    b
     * @return {@code E}
     */
    void apply(List<E> list, BaseMapper<F> b );
}

提取公共的类属性,关联属性

public class Entity {

    private Long id;

    /**
     * 资源url
     */
    @TableField(exist = false)
    String resourceUrl;
}

相同的实体


public class BlackboardEntity extends Entity{
    /**
     * id
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 标题
     */
    @TableField(value = "title")
    private String title;
    /**
     * 阶段学习
     */
    @TableField(value = "phase_studying")
    private String phaseStudying;
    /**
     * 主题
     */
    @TableField(value = "subject")
    private String subject;
}
public class FilesEntity extends Entity{
 /**
     * id
     */
    @TableId(type = IdType.AUTO)
    Long id;
    /**
     * 资源id
     */
    @TableField
    Long resourceId;
    /**
     * 资源url
     */
    @TableField
    String resourceUrl;
    /**
     * 资源名称
     */
    @TableField
    String resourceName;
}
   

接口抽象

/**
 * 资源服务
 *
 * @author bcf
 * @date 2022/09/16
 */
public interface ResourceService<E extends Entity,F extends FilesEntity> {


    /**
     * 制定战略
     *
     * @param strategy 策略
     */
    void setStrategy(IService<E> strategy);

    /**
     * 教学文件集实体基础映射器
     *
     * @param FilesEntityBaseMapper 教学文件实体基础映射器
     */
     void setFilesEntityBaseMapper(BaseMapper<F> FilesEntityBaseMapper);

    /**
     * 页面
     *
     * @param ResourceDto 教学资源dto
     * @return {@code IPage<E>}
     */
    IPage<E> page(ResourceDto ResourceDto);


    /**
     * 通过id
     *
     * @param id id
     * @return {@code E}
     */
    E getById(Long id);


    /**
     * 更新通过id
     *
     * @param e      e
     * @param eClass e类
     * @return {@code Boolean}
     * @throws InstantiationException 实例化异常
     * @throws IllegalAccessException 非法访问异常
     */
    Boolean updateById(E e, Class<F> eClass) throws InstantiationException, IllegalAccessException;
}

策略实现


/**
 * 资源服务实现
 *
 * @date 2022/09/16
 */
public class ResourceServiceImpl<E extends Entity, F extends FilesEntity> implements ResourceService<E, F> {

    /**
     * 策略
     */
    private IService<E> strategy;

    /**
     * 教学文件实体基础映射器
     */
    private BaseMapper<F> FilesEntityBaseMapper;

    /**
     * 
     * 资源服务实现
     */
    public ResourceServiceImpl() {
    }

    /**
     * 制定战略
     *
     * @param strategy 策略
     */
    @Override
    public void setStrategy(IService<E> strategy) {
        this.strategy = strategy;
    }

    /**
     * 教学文件集实体基础映射器
     *
     * @param FilesEntityBaseMapper 教学文件实体基础映射器
     */
    @Override
    public void setFilesEntityBaseMapper(BaseMapper<F> FilesEntityBaseMapper) {
        this.FilesEntityBaseMapper = FilesEntityBaseMapper;
    }


    /**
     * 获得资源函数
     *
     * @return {@code ResourceFunc<E, F>}
     */
    public ResourceFunc<E, F> getResourceFunc() {
        return (e, b) -> {
            List<Long> ids = e.stream().map(Entity::getId).collect(Collectors.toList());
            if (ids.size() > 0) {
                Map<Long, List<F>> map = b.selectList(
                        new LambdaQueryWrapper<F>().in(F::getResourceId, ids)
                ).stream().collect(
                        Collectors.groupingBy(F::getResourceId)
                );
                e.forEach(
                        item -> {
                            if (map.containsKey(item.getId())) {
                                item.setResourceUrl(map.get(item.getId()).get(0).getResourceUrl());
                            }
                        }
                );
            }
        };
    }


    /**
     * 页面
     *
     * @param ResourceDto 教学资源dto
     * @return {@code IPage<E>}
     */
    @Override
    public IPage<E> page(ResourceDto ResourceDto) {
        IPage<E> page = new Page<>(ResourceDto.getCurrent(), ResourceDto.getSize());
        LambdaQueryWrapperUtils<E> lambdaQueryWrapperUtils = new LambdaQueryWrapperUtils<>();
        lambdaQueryWrapperUtils.schoolFilter(ResourceDto);
        lambdaQueryWrapperUtils.eq(StringUtils.isNotEmpty(ResourceDto.getSubject()), "subject", ResourceDto.getSubject());
        lambdaQueryWrapperUtils.eq(StringUtils.isNotEmpty(ResourceDto.getTitleName()), "title", ResourceDto.getTitleName());
        page = this.strategy.page(page, lambdaQueryWrapperUtils);
        getResourceFunc().apply(page.getRecords(), FilesEntityBaseMapper);
        return page;
    }

 
    /**
     * 通过id
     *
     * @param id id
     * @return {@code E}
     */
    @Override
    public E getById(Long id) {
        E obj = this.strategy.getById(id);
        List<F> list = FilesEntityBaseMapper.selectList(
                new LambdaQueryWrapper<F>().eq(F::getResourceId, id)
        );
        if (list.size() > 0) {
            obj.setResourceUrl(list.get(0).getResourceUrl());
        }
        return obj;
    }

    /**
     * 更新通过id
     *
     * @param e      e
     * @param fClass f类
     * @return {@code Boolean}
     * @throws InstantiationException 实例化异常
     * @throws IllegalAccessException 非法访问异常
     */
    @Override
    public Boolean updateById(E e, Class<F> fClass) throws InstantiationException, IllegalAccessException {
        this.FilesEntityBaseMapper.delete(
                new LambdaQueryWrapper<F>().eq(F::getResourceId, e.getId())
        );
        F obj = fClass.newInstance();
        obj.setResourceUrl(e.getResourceUrl());
        obj.setResourceId(e.getId());
        this.FilesEntityBaseMapper.insert(obj);
        return this.strategy.updateById(e);
    }
}

测试

@Resource
private BlackboardService BlackboardService;

@Resource
private FilesDao FilesDao;

public static final ResourceService<BlackboardEntity, FilesEntity> ResourceService =
        new ResourceServiceImpl<>();

/**
 * 初始化后
 */
@PostConstruct
public void afterInit(){
    ResourceService.setStrategy(BlackboardService);
    ResourceService.setFilesEntityBaseMapper(FilesDao);
}

/**
 * 页面
 *
 * @param ResourceDto 教学资源dto
 * @return {@code Result<IPage<BlackboardEntity>>}
 */
@PostMapping("/page")
public Result<IPage<BlackboardEntity>> page(@RequestBody ResourceDto ResourceDto) {

    return Result.ok(ResourceService.page(ResourceDto));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值