引入MybatisPlus后对分层结构的影响以及解决方案

    在之前写分层模型以及代码工程化规范的时候写到了分层规范中有说到DAO数据层,当项目架构中只有Mybatis的时候显然mapper接口(实际是mapper接口在Mybatis中生成的代理类)本身就是DAO层,但当引入MybatisPlus以后,分层结构会收到什么样的影响呢?应该如何处理这样的影响?本文主要探讨的就是这两个问题。

一、多了一层?

    显而易见的是,MybatisPlus操作数据库是对Mybatis的mapper进行了通用扩展,同时提供了通用操作的api,当使用MybatisPlus的api时,放在service个人认为并不那么合适的,原因是其api带有sql条件的构造,希望能尽量抽出一层来写MybatisPlus的代码。
    但是如果抽出一层,这一层和mapper都是操作数据库的DAO层,使用和维护的时候会对程序员造成一定的困扰,service层的代码中既有Mapper又有DAO。另一方面,会造成纯sql维护在Mapper中,MybatisPlus的API使用封装在DAO中,由于Mapper中有MybatisPlus的扩展,分开维护后导致职责不清,且会造成一定的歧义和不便。
    总结起来,如果多一层,一方面,两种组件一起工作,对编程造成了一定的影响,另一方面,两种组件分别各自维护,其中一个组件却拥有一部分另一个组件的能力,维护起来并不方便,且容易混淆。

二、架空Mapper

    那么可以想到的是可以把Mapper架空,单独维护DAO,如果需要调用mapper,就通过DAO去调用。
    当然,这样做是可以的,但是很大程度上依赖于口头约定,并且需要强手动维护DAO,每次Mapper增加方法,DAO需要同时增加方法,但是也可以不去加,而不加的话,会导致有些程序员偷懒直接去调用Mapper。
    另一方面,没有约束的维护,导致规范性不强。
    所以我们应该怎么做?

三、 引入装饰器模式

    先说一下引入装饰器模式以后的类结构图:
引入MybatisPlus后对分层结构的影响以及解决方案_第1张图片

    这里使用了装饰器模式,这样做的好处是:

  1. DAO做了增强,同时整合了Mapper和MybatisPlus所有的能力,可以在同一个地方进行维护;
  2. 强制性的接口实现被迫让DAO必须和Mapper保持一致,DAO可以利用MybatisPlus的能力做自己的扩展,而Mapper扩展自己的同时强制DAO同时扩展,维护起来不会混乱,更加规范化管理和维护,维护成本更低;
  3. 架空Mapper,避免多组件同时使用。

    事实上,从Mapper本身的角度来看,也是对Mybatis的一种扩展,这里使用装饰器模式刚好也符合这一特点,正如装饰器本身的作用:允许向一个现有的对象添加新的功能,同时又不改变其结构

    (另外需要说明的一点,BaseDAO的作用只是为了让装饰器模式中统一的代码放在一起,减少创建DAO时要编写的代码,并不是装饰器模式的主体部分。)

四、 沿伸

    提出一个问题:这里为什么是装饰器模式,而不是代理模式?
    我们知道,代理模式和装饰器模式是非常相似的,那为什么这里是装饰器模式,而不是代理模式呢?
    代理模式本身更侧重于代理,它是对原始接口已有能力的一个代理和扩展,并且自己将代理对象管理起来,并不对外暴露。
    而装饰器模式更侧重于功能增强,可以是已有能力,也可以是派生能力,且组合的对象可以对外暴露,由外部传入。
    上述方案的组合对象由spring从外部注入,且功能上更侧重于功能增强。因此,这里采用的就是装饰器模式。

总结

    其实个人在选择这样的写法之前是下意识的,可能因为平时使用的设计模式比较多,自然而然选择了装饰器模式,而回过头来分析,选择装饰器模式也确实可以带来很大的便利性,上述也分析过了。可能还有很多种解决方案,如果这篇文章有人看的话可以提出自己的想法和意见。

你可能感兴趣的:(设计模式,java,mybatis)