zoukankan      html  css  js  c++  java
  • 设计模式原理及应用·组合模式

    前言

    在互联网系统中,Java语言大行其道。越来越多的开源框架,商业框架应用在web项目中,越来越多的组件被创建,大大提高了网站开发效率,使得开发者越发的可以专注于业务逻辑而非系统辅助组件的实现。
    
    但是,在有了框架的帮助之后,许多人容易产生误解,框架提供的功能强大,我们不需要写很多的辅助功能,专注于业务的时候没机会,或者不需要使用设计模式。
    
    这里有个观点,写业务没什么技术含量,也不需要什么高深的模式。对于这个想法,业务同学表示,这个锅...它不背。
    

    一、原理

    1.1 介绍

    组合模式通常的作用:定义整体与部分,并定义集体动作。很多资料也会将其描述为“主干”和“叶子”,这是从树形结构上来进行描述。
    
    • 定义“人在吃饭”。整体是人,集体动作是”吃饭“,部分是需要配合的手和嘴,动作是“吃饭”。
    • 定义“施工队修路”。整体是施工队,集体动作是”修路“,部分是施工队中的人,器械,等等,动作是”修路“。
    • 还有很多,以一个整体对外暴露接口,但是每个部分实现接口的方式各不一样。

    1.2 结构图

    组合模式的组成:

    • 集体动作:如图BaseOperation,集体动作是doOperate()。
    • 部分1:ComponentOperator1,它实现了doOperate()。
    • 部分2:ComponentOperator2,它实现了doOperate()。
    • 整体:CompositeOperator,它将各个部分组合起来,并以整体的身份执行doOperate();
      关于compositeOperator怎么将各个组件部分给串联起来作为整体,其实从上面UML图可知,使用的是list,里面保存了所有BaseOperation的实现类,在运行时,将循环执行,后续在例子中会详细看到它的运行机制。

    规范的命名可以帮助我们更好的了解程序,例如:我们去spring源码中搜索”composite...“将得到很多的类,他们都是使用组合模式,而且我们可以通过查看他们实现的接口和定义的List知道他们的运作机制

    二、应用

    组合模式算是应用比较多的设计模式之一,我们很容易就在框架中找到它,也很容易在业务系统中找到它的应用场景。
    

    2.1 spring框架

    首先:在spring源码中搜索类“composite”。我们可以得到:
    

    相逢即是缘,我们分析下CompositeCacheManager中,组合模式的实现方式。

    首先要有以下概念:
    
    • 既然使用了Composite*的命名,以框架的命名规范来讲,这必然是组合模式中的组合组件(将各个组件组合到一起);
    • 组合组件中,必然有List,T是接口规范;
    • 组合组件也是“集体动作”的实现类。

    关系

    UML图

    CompositeCacheManager如何实现接口方法

    	private final List<CacheManager> cacheManagers = new ArrayList<>();
    
    	...
        ...
    
    	// 直接遍历list,返回所有的cache
    	@Override
    	@Nullable
    	public Cache getCache(String name) {
    		for (CacheManager cacheManager : this.cacheManagers) {
    			Cache cache = cacheManager.getCache(name);
    			if (cache != null) {
    				return cache;
    			}
    		}
    		return null;
    	}
    
    	@Override
    	public Collection<String> getCacheNames() {
    		Set<String> names = new LinkedHashSet<>();
    		for (CacheManager manager : this.cacheManagers) {
    			names.addAll(manager.getCacheNames());
    		}
    		return Collections.unmodifiableSet(names);
    	}
    

    小结

    在spring上例中,对于组合模式的实现,算是比较经典的,没有多余的操作,组合模式的结构和功能均得以体现。
    

    分析spring源码技巧一:了解设计模式,如果在源码阅读中,看到设计模式,先去看看设计模式的用法以及组件,再联系spring的功能,分析每个方法,每个属性的作用。既学习了设计模式的用法,又能从设计的角度理解spring源码。

    2.2 业务场景

    需求:

    在api系统中,需要安全模块对于外部请求进行安全校验。现在需要校验3个模块。分别是请求签名校验,ip白名单对应,客户端权限校验。

    分析:采用组合模式

    • 集体动作:校验是否通过
    • 组件1:签名校验
    • 组件2:白名单校验
    • 组件3:客户权限校验

    程序设计:

    **程序实现:**
    
    • AOP进行精确拦截,(过滤器,拦截器皆可,根据实际业务需求)。
    • 定义context传递上下文,并将每个组件处理的“拒绝原因”写入上下文。
    • 定义manager调用CompositeComponentAuthority的permit()方法。

    核心代码:

    manager管理器

           	private CompositeComponentAuthority authority;	
           
           	/**
                * 校验权限
                * @param joinPoint
                */
               public Object checkAuthority(ProceedingJoinPoint joinPoint) throws Throwable {
           
                   // 1.获取请求上下文
                   ParamContext paramContext = this.getParamContext(joinPoint);
           
                   // 2.去鉴权
                   boolean permission = authority.permit(paramContext);
           
                   // 3.鉴权不通过则直接返回
                   if (!permission) {
                       return paramContext.getReturnMap();
                   }
           
                   // 4.放行
                   return joinPoint.proceed();
               }
    

    CompositeComponentAuthority核心

                  /**
                   * autowired可以注入所有的<T>的实现类,并根据实现类的Order进行排序
                   */
              	@Autowired(required = false)
                  private List<ApiAuthority> items = new LinkedList<>();
              
                  @Override
                  public Boolean permit(ParamContext context) {
              
                      if (CollectionUtils.isEmpty(items)) {
                          return true;
                      }
                      boolean permision;
                      for (ApiAuthority authority : items) {
                          permision = authority.permit(context);
                          if (!permision){
                              return permision;
                          }
                      }
              
                      return true;
                  }
    

    小结:
    组合模式还有很多用途,不一一举例,在我服务的公司里面,在现有系统,就不止一处业务使用到组合模式。它的应用场景还是很多的,我们只需要理解“整体-部分”的概念,最好再看看框架中他们如何被实现,在写业务时,你也可以设计出更好的结构。

  • 相关阅读:
    js--未来元素
    Nginx 浏览器打开是下载状态
    JS对象的深拷贝
    微信小程序--扫描二维码
    js--call( )/apply()/bind()--应用
    数学书籍
    【活动】你有创意我有奖!摹客X飞书2020产品设计大赛邀你来战
    APP设计实例解析,深色模式为什么突然就火了?
    焦虑求职季又至:2020UI设计师作品集如何准备?
    QQ音乐 vs 网易云音乐,用户体验哪家强?
  • 原文地址:https://www.cnblogs.com/dhcao/p/11046131.html
Copyright © 2011-2022 走看看