设计模式原理及应用·组合模式

前言

在互联网系统中,Java语言大行其道。越来越多的开源框架,商业框架应用在web项目中,越来越多的组件被创建,大大提高了网站开发效率,使得开发者越发的可以专注于业务逻辑而非系统辅助组件的实现。

但是,在有了框架的帮助之后,许多人容易产生误解,框架提供的功能强大,我们不需要写很多的辅助功能,专注于业务的时候没机会,或者不需要使用设计模式。

这里有个观点,写业务没什么技术含量,也不需要什么高深的模式。对于这个想法,业务同学表示,这个锅...它不背。

一、原理

1.1 介绍

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

1.2 结构图

1328967-20190618164617426-1510715941.png

组合模式的组成:

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

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

二、应用

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

2.1 spring框架

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

1328967-20190618164634564-1857522436.png

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

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

关系
1328967-20190618164650649-1589457707.png

1328967-20190618164703147-1767117451.png

UML图
1328967-20190618164807753-1068955885.png

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:客户权限校验

程序设计:
1328967-20190618164837286-1341835455.png

**程序实现:**
  • 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;
              }

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

转载于:https://www.cnblogs.com/dhcao/p/11046131.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值