zoukankan      html  css  js  c++  java
  • 【一起学设计模式】访问者模式实战:权限管理树删除节点操作

    前言

    申明:
    本文章首发自本人博客: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

  • 相关阅读:
    UVALive 6909 Kevin's Problem 数学排列组合
    UVALive 6908 Electric Bike dp
    UVALive 6907 Body Building tarjan
    UVALive 6906 Cluster Analysis 并查集
    八月微博
    hdu 5784 How Many Triangles 计算几何,平面有多少个锐角三角形
    hdu 5792 World is Exploding 树状数组
    hdu 5791 Two dp
    hdu 5787 K-wolf Number 数位dp
    hdu 5783 Divide the Sequence 贪心
  • 原文地址:https://www.cnblogs.com/wang-meng/p/11982661.html
Copyright © 2011-2022 走看看