【一起学设计模式】访问者模式实战:权限管理树删除节点操作

前言

申明:
本文章首发自本人博客:https://www.cnblogs.com/wang-meng 和公众号:壹枝花算不算浪漫 如若转载请标明来源

之前在我的博客(一枝花算不算浪漫)中已经更新过两篇设计模式相关的内容

上面内容都是基于真实业务场景精简后的设计(工作中真实场景使用到的)。

之前为了学习设计模式,看过网上很多相关博客讲解,大都是画下UML类图,举例几个毫不相干的demo,看了几遍仍然是云里雾里。

学习设计模式只有在真正的业务场景去使用才会更好的理解其精髓。这里举例自己工作中电商的业务场景,然后配合一些业务功能的实现,来学会设计模式,使自己的代码更优雅。

业务背景

权限功能模块-权限树-删除树上的某个权限

  1. 要求判断该权限节点及其子节点是否有用户、角色关联,如若有关联则不允许删除
  2. 要求删除该权限节点及其子节点所有数据

常规操作

先说下大多数人为了实现需求都会做的常规操作,这里举例说明,权限A,其子节点B、C

  1. 查找权限A是否被用户、角色关联过
  2. 查找全新啊A下面所有子节点B、C
  3. 查找权限B、C是否被其他用户、角色关联过
  4. 删除A、B、C

这里如果有个流程图效果会更佳,但是相信大家看到文字也能明白其中的运转流程。

这里只是简单地列了下操作的步骤,其实大家可能会做的更好,比如查询、删除 都可以批量去做处理,这里就不再讨论了。

通过上面的流程,我们知道一个方法就可以搞定这几个步骤,只是该方法包含了查询、删除等等逻辑操作,看起来并不精简。

访问者模式实现

  1. 实现类图
    09D8AF63-1056-42EA-A65A-833B55F9BA6A.png

  2. 代码实现
    这里使用访问者模式 分开一个检查relatePriorityNode的visitor,还有一个removeNode的visitor,如果以后扩展其他操作方式直接增加新的visitor即可。

PriorityNode:

/**
 * 权限树节点
 * @author wangmeng
 *
 */
@Data
public class PriorityNode {

	/**
	 * id
	 */
	private Long id;
	/**
	 * 权限编号
	 */
	private String code;
	/**
	 * 权限URL
	 */
	private String url;
	/**
	 * 权限备注
	 */
	private String priorityComment;
	/**
	 * 权限类型
	 */
	private Integer priorityType;
	/**
	 * 父权限id
	 */
	private Long parentId;
	/**
	 * 权限的创建时间
	 */
	private Date gmtCreate;
	/**
	 * 权限的修改时间
	 */
	private Date gmtModified;
	/**
	 * 子权限节点
	 */
	private List<PriorityNode> children = new ArrayList<PriorityNode>();
	
	/**
	 * 接收一个权限树访问者
	 * @param visitor 权限树访问者
	 */
	public void accept(PriorityNodeVisitor visitor) {
		visitor.visit(this);  
	}
}

PriorityNodeVisitor:

/**
 * 权限树节点的访问者接口
 *
 * @author wangmeng
 * @blog https://www.cnblogs.com/wang-meng/
 * @create 2019-12-01 10:12
 **/
public interface PriorityNodeVisitor {

	/**
	 * 访问权限树节点
	 *
	 * @param node 权限树节点
	 */
	void visit(PriorityNode node);
}

AbstractNodeVisitor:

/**
 * @author wangmeng
 * @blog https://www.cnblogs.com/wang-meng/
 * @create 2019-12-01 10:26
 **/
public abstract class AbstractNodeVisitor implements PriorityNodeVisitor{

	private PriorityService priorityService;

	public AbstractNodeVisitor(PriorityService priorityService) {
		this.priorityService = priorityService;
	}

	@Override
	public void visit(PriorityNode node) {
		List<PriorityDTO> priorityDTOList = priorityService.listChildPriorities(node.getId());
		if (CollectionUtils.isNotEmpty(priorityDTOList)) {
			for (PriorityDTO priorityDTO : priorityDTOList) {
				PriorityNode priorityNode = new PriorityNode();
				BeanUtils.copyProperties(priorityDTO, priorityNode);
				// 使用递归处理
				priorityNode.accept(this);
			}
		}

		operateNode(node);
	}

	/**
	 * 操作权限树
	 * @param node 树节点
	 */
	abstract void operateNode(PriorityNode node);
}

PriorityNodeRelateCheckVisitor:

/**
 * 权限树节点的关联检查访问者
 *
 * @author wangmeng
 * @blog https://www.cnblogs.com/wang-meng/
 * @create 2019-12-01 10:19
 **/
public class PriorityNodeRelateCheckVisitor extends AbstractNodeVisitor{

	/**
	 * 关联检查结果
	 */
	private Boolean relateCheckResult = false;
	/**
	 * 权限管理模块的service组件
	 */
	private PriorityService priorityService;
	/**
	 * 角色和权限关系管理模块的DAO组件
	 */
	private RolePriorityRelationshipService rolePriorityRelationshipService;
	/**
	 * 账号和权限关系管理模块的Service组件
	 */
	private AccountPriorityRelationshipService accountPriorityRelationshipService;

	/**
	 * 构造函数
	 */
	public PriorityNodeRelateCheckVisitor(PriorityService priorityService,
										  RolePriorityRelationshipService rolePriorityRelationshipService,
										  AccountPriorityRelationshipService accountPriorityRelationshipService) {
		super(priorityService);
		this.priorityService = priorityService;
		this.rolePriorityRelationshipService = rolePriorityRelationshipService;
		this.accountPriorityRelationshipService = accountPriorityRelationshipService;
	}

	@Override
	void operateNode(PriorityNode node) {
		Long nodeId = node.getId();
		// 检查权限是否被任何一个角色或者是账号关联了,如果被任何一个角色或者账号关联,则relateCheckResult=true
		int roleRelatedCount = rolePriorityRelationshipService
				.selectCount(new EntityWrapper<RolePriorityRelationship>().eq("priority_id", nodeId));
		if(roleRelatedCount > 0) {
			this.relateCheckResult = true;
		}
		int accountRelatedCount = accountPriorityRelationshipService
				.selectCount(new EntityWrapper<AccountPriorityRelationship>().eq("priority_id", nodeId));
		if(accountRelatedCount > 0) {
			this.relateCheckResult = true;
		}

		this.relateCheckResult = false;
	}

	public Boolean getRelateCheckResult() {
		return relateCheckResult;
	}
}

PriorityNodeRemoveVisitor:

/**
 * 权限树节点的删除访问者
 *
 * @author wangmeng
 * @blog https://www.cnblogs.com/wang-meng/
 * @create 2019-12-01 10:13
 **/
public class PriorityNodeRemoveVisitor extends AbstractNodeVisitor{

	private PriorityService priorityService;

	/**
	 * 构造函数
	 * @param priorityService 权限service
	 */
	public PriorityNodeRemoveVisitor(PriorityService priorityService) {
		super(priorityService);
		this.priorityService = priorityService;
	}

	@Override
	void operateNode(PriorityNode node) {
		// 删除权限
		priorityService.deleteById(node.getId());
	}
}

调用地方 PriorityServiceImpl:

@Override
	public Boolean removePriority(Long id) {
		try {
			// 根据id查询权限
			Priority priorityDO = baseMapper.selectById(id);
			PriorityNode priorityNode = priorityDO.clone(PriorityNode.class);

			// 检查这个权限以及其下任何一个子权限,是否被角色或者账号给关联着
			PriorityNodeRelateCheckVisitor relateCheckVisitor = new PriorityNodeRelateCheckVisitor(
					this, rolePriorityRelationshipService, accountPriorityRelationshipService);
			relateCheckVisitor.visit(priorityNode);
			Boolean relateCheckResult = relateCheckVisitor.getRelateCheckResult();

			if(relateCheckResult) {
				return false;
			}

			// 递归删除当前权限以及其下所有的子权限
			PriorityNodeRemoveVisitor removeVisitor = new PriorityNodeRemoveVisitor(this);
			removeVisitor.visit(priorityNode);
		} catch (Exception e) {
			 log.error("error", e);
			return false;
		}

		return true;
	}

申明:
本文章首发自本人博客:https://www.cnblogs.com/wang-meng 和公众号:壹枝花算不算浪漫 如若转载请标明来源

申明

本文章首发自本人博客:https://www.cnblogs.com/wang-meng 和公众号:壹枝花算不算浪漫,如若转载请标明来源!

感兴趣的小伙伴可关注个人公众号:壹枝花算不算浪漫

22.jpg

posted @ 2019-12-04 14:28  一枝花算不算浪漫  阅读(491)  评论(0编辑  收藏  举报