【项目实战】去除繁琐的if..else 优雅使用策略模式
2020-04-19 20:58
573 查看
项目需求
最新开发系统权限管理系统时,有这样一个需求,不同角色的数据权限不一样需要做处理 根据数据范围拥有不同部门的数据查看权限, 比如这样
if (全部) { 获取全部部门ids } else if (本级) { 当前用户部门id } else if (本金以及子级) { 当前用户部门以及子部门ids } else { 自定义的部门ids }目前只是4层,虽然这样容易理解,逻辑清晰,但是虽然系统的拓展,if...else太多,这个就很可怕了。 因此使用策略模式来消除掉if else。
策略模式是一种解耦的方法,它对算法进行封装,使得算法的调用和算法本身分离。使用策略模式客户端代码不需要调整,算法之间可以互相替换,因为不同的算法实现的是同一个接口。将上面的代码优化后变为:
@Autowired private DataScopeContext dataScopeContext; // 根据数据权限范围查询直接通过同一个dohandler方法根据不同的tag去选择处理不同的逻辑部门ids List<Integer> ids = dataScopeContext.getDeptIdsForDataScope(roleDto, roleDto.getDsType());用户在选择不同数据范围时,由context上下文进行判断选择资源去资源池调用,直接通过同一个getDeptIdsForDataScope方法根据不同的类型去选择处理不同的逻辑,从而实现结构上的优化。 具体逻辑就是: 定一个策略handler接口,然后各个策略类去实现这个handler接口,并实现处理逻辑。 然后定一个定义策略上下文,通过Spring将实现Strategy的实现类都自动注入到strategyMap类中,根据type获取对应的策略 代码展示: 策略接口AbstractDataScopeHandler类
/** * @Classname AbstractDataScopeHandler * @Description 创建抽象策略角色 主要作用 数据权限范围使用 * @Author Created by Lihaodong (alias:小东啊) lihaodongmail@163.com * @Date 2019-06-08 15:45 * @Version 1.0 */ public interface AbstractDataScopeHandler { /** * @param roleDto * @param dataScopeTypeEnum * @return */ List<Integer> getDeptIds(RoleDTO roleDto, DataScopeTypeEnum dataScopeTypeEnum); }策略类实现这个策略接口(只展现一种)
package com.xd.pre.strategy; import com.xd.pre.constant.DataScopeTypeEnum; import com.xd.pre.domain.SysDept; import com.xd.pre.dto.RoleDTO; import com.xd.pre.service.ISysDeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Collectors; /** * @Classname AllDataScope * @Description 所有 * @Author Created by Lihaodong (alias:小东啊) lihaodongmail@163.com * @Date 2019-06-08 16:27 * @Version 1.0 */ @Component("1") public class AllDataScope implements AbstractDataScopeHandler { @Autowired private ISysDeptService deptService; // 执行逻辑 @Override public List<Integer> getDeptIds(RoleDTO roleDto, DataScopeTypeEnum dataScopeTypeEnum) { List<SysDept> sysDepts = deptService.list(); return sysDepts.stream().map(SysDept::getDeptId).collect(Collectors.toList()); } }Service注入策略集合,根据type获取对应的策略
package com.xd.pre.strategy; import com.xd.pre.constant.DataScopeTypeEnum; import com.xd.pre.dto.RoleDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @Classname DataScopeContext * @Description 创建环境角色Context: * @Author Created by Lihaodong (alias:小东啊) lihaodongmail@163.com * @Date 2019-06-08 16:11 * @Version 1.0 */ @Service public class DataScopeContext { @Autowired private final Map<String, AbstractDataScopeHandler> strategyMap = new ConcurrentHashMap<>(); /** * Component里边的1是指定其名字,这个会作为key放到strategyMap里 * @param strategyMap */ public DataScopeContext(Map<String, AbstractDataScopeHandler> strategyMap) { strategyMap.forEach(this.strategyMap::put); } public List<Integer> getDeptIdsForDataScope(RoleDTO roleDto, Integer type) { return strategyMap.get(String.valueOf(type)).getDeptIds(roleDto, DataScopeTypeEnum.valueOf(type)); } }服务层调用getDeptIdsForDataScope方法
通过这个,就可以看到通过在不同的类型获取不同部门ids,可以自动的拿到不同的资源。
使用策略模式的好处就是通过一个封装的上下文可以自由的切换不同的算法,省去多重判断,同时可以具有很好的扩展性。
当策略过多的时候就会显得很臃肿,建议大家合理的运用设计模式 具体的项目实战可以参考我的开源项目进行理解:
项目地址: https://gitee.com/li_haodong/pre
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- 使用策略模式减少if else
- 设计模式——行为型模式之借助策略模式(Strategy Pattern)减少使用不必要的if-else if -else和switch-case(三)
- 项目重构--使用策略模式
- 状态模式——省去if-else的繁琐结构
- 结合策略模式和HashMap摆脱if else
- 设计模式实战(一)——使用策略模式(strategy pattern)实现多关键字排序
- 使用命令模式,告别if-else
- 使用反射+策略模式代替项目中大量的switch case判断
- 关于使用SPI来减少项目中的if else判断
- 利用策略模式和工厂模式优化代码中过多的if-else
- 设计模式实战(一)——使用策略模式(strategy pattern)实现多关键字排序
- 设计模式-策略模式Strategy以及消灭if else
- 学会了处理项目中那些没有确定方案的东西(使用“策略模式”)
- Android设计模式 -- 巧用策略模式告别过多的 if...else...
- 策略模式:再见if-else
- 利用设计模式替代项目中的if else(转)
- 第十周项目6-吃饭,睡觉,打豆豆(不使用自定义函数)(使用if-else语句)
- 去除if..else...语句的模式
- 架构 之 使用子类多态 and 使用state模式(使用面向对象技术替代switch-case和if-else)
- iOS项目开发实战——UIImageView的使用与图片显示模式