当前位置:首页 > 科技  > 软件

分层设计:Service 层真的需要实现接口吗?

来源: 责编: 时间:2024-05-07 09:06:17 283观看
导读前几天看技术交流群的话题,又刷到了Service 层和 Dao 层真的有必要每个类都加上接口吗?这个问题,之前简单回答了一波,给出的观点是看情况现在结合我参与的项目以及阅读的一些项目源码来看,如果项目中使用了像 Spring 这样

前几天看技术交流群的话题,又刷到了Service 层和 Dao 层真的有必要每个类都加上接口吗?这个问题,之前简单回答了一波,给出的观点是看情况TvI28资讯网——每日最新资讯28at.com

现在结合我参与的项目以及阅读的一些项目源码来看,如果项目中使用了像 Spring 这样的依赖注入框架,那可以不用接口!TvI28资讯网——每日最新资讯28at.com

先来说说为什么使用了依赖注入框架以后,可以不使用接口。TvI28资讯网——每日最新资讯28at.com

我整理了支持 Service 层和 Dao 层需要加上接口的理由,总结下来就这么三个:TvI28资讯网——每日最新资讯28at.com

  • 可以在尚未实现具体 Service 逻辑的情况下编写上层代码,如 Controller 对 Service 的调用
  • Spring 默认是基于动态代理实现 AOP 的,动态代理需要接口
  • 可以对 Service 进行多实现

实际上,这三个理由都站不住脚!TvI28资讯网——每日最新资讯28at.com

先说说第一个理由:「上层可以在下层逻辑没有实现的情况下进行编码」!很典型的面向接口编程,对层与层之间进行了解耦,看起来好像没有问题。TvI28资讯网——每日最新资讯28at.com

这种开发方式适合不同模块之间是由不同的人或项目组开发的,因为沟通的成本比较大。同时避免由于项目组之间开发进度的差异而相互影响。TvI28资讯网——每日最新资讯28at.com

不过让我们回想一下,在一般项目开发里面,有多少项目组是按层来切分开发任务的呢?实际上,大部分的项目都是按照功能划分的。即使是现在前后端分离的情况,单纯的后端开发也是按照功能模块进行任务划分,即一个人负责从 Controller 层到 DAO 层的完整逻辑处理。在这种情况下,每一层都先定义一个接口,再去实现逻辑,除了增加了开发人员的工作量(当然,如果代码量计入工作量的话,那开发人员应该也不是太排斥接口的!),实际没有任何用处。TvI28资讯网——每日最新资讯28at.com

如果开发人员想在下层逻辑没有完成的情况下,先开发上层逻辑,可以先编写下层类的空方法来先完成上层的逻辑。TvI28资讯网——每日最新资讯28at.com

这里推荐一个个人比较喜欢的开发流程,自上向下的编码流程:TvI28资讯网——每日最新资讯28at.com

  • 先在 Controller 层编写逻辑,遇到需要委托 Service 调用的地方,直接先写出调用代码。
  • 优先完成 Controller 层的流程
  • 然后使用 IDE 的自动补全,对刚才调用下层的代码生成对应的类和方法,在里面添加 TODO
  • 等所有的类和方法都补全了,再基于 TODO,按照上面的流程去一个个的完善逻辑。
  • 此方法可以使你对业务流程有比较好的理解。

对于第二个理由,就完全不成立了。Spring 默认是基于动态代理的,不过通过配置是可以使用 CGLib 来实现 AOP。CGLib 是不需要接口的。TvI28资讯网——每日最新资讯28at.com

最后一个理由是可以对 Service 进行多实现。这个理由不充分,或者说没有考虑场景。实际上在大多数情况下是不需要多实现,或者说可以使用其它方式替代基于接口的多实现。TvI28资讯网——每日最新资讯28at.com

另外,对于很多使用了接口的项目,项目结构也是有待商榷的!下面,我们结合项目结构来说明。TvI28资讯网——每日最新资讯28at.com

一般项目结构都是按层来划分的,如下所示:TvI28资讯网——每日最新资讯28at.com

  • Controller
  • Service
  • Dao

对于不需要多实现的情况,也就不需要接口了。上面的项目结构即可满足要求。TvI28资讯网——每日最新资讯28at.com

对于需要多实现的情况,无论是现在需要,还是后面需要。这种情况下,看起来好像是需要接口。此时的项目结构看起来像这样:TvI28资讯网——每日最新资讯28at.com

  • Controller
  • Service

— 接口在一个包中TvI28资讯网——每日最新资讯28at.com

impl — 实现在另一个包里TvI28资讯网——每日最新资讯28at.com

  • Dao

对于上面的结构,我们来考虑多实现的情况下,该怎么处理?TvI28资讯网——每日最新资讯28at.com

第一种方式,是在 Service 中新增一个包,在里面编写新的逻辑,然后修改配置文件,将新实现作为注入对象。TvI28资讯网——每日最新资讯28at.com

  • Controller
  • Service

—- 接口在一个包中TvI28资讯网——每日最新资讯28at.com

impl —实现在另一个包里TvI28资讯网——每日最新资讯28at.com

impl2 —新实现在另一个包里TvI28资讯网——每日最新资讯28at.com

  • Dao

第二种方式,是新增一个 Service 模块,在里面编写新的逻辑(注意这里的包和原来 Service 的包不能相同,或者包相同,但是类名不同,否则无法创建类。因为在加载时需要同时加载两个 Service 模块,如果包名和类名都相同,两个模块的类全限定名就是一样的了!),然后修改配置文件,将新逻辑作为注入对象。TvI28资讯网——每日最新资讯28at.com

  • Controller
  • Service

—- 接口在一个包中TvI28资讯网——每日最新资讯28at.com

impl —实现在另一个包里TvI28资讯网——每日最新资讯28at.com

  • Service2
  • impl2 —新实现在另一个包里TvI28资讯网——每日最新资讯28at.com

  • DaoTvI28资讯网——每日最新资讯28at.com

相对而言,实际第一种方式相对更简单一点,只需要关注包层面。而第二种方式需要关注模块和包两个层面。另外,实际这两种方式都导致了项目中包含了不需要的逻辑代码。因为老逻辑都会被打进包里。TvI28资讯网——每日最新资讯28at.com

不过,从结构上来看,实际方式二的结构要比方式一的结构更清晰,因为从模块上能区分逻辑。TvI28资讯网——每日最新资讯28at.com

那有没有办法来结合两者的优点呢?答案是肯定的,而且操作起来也不复杂!TvI28资讯网——每日最新资讯28at.com

首先将接口和实现独立开,作为一个独立的模块:TvI28资讯网——每日最新资讯28at.com

  • Controller
  • Service — 接口模块

ServiceImplTvI28资讯网——每日最新资讯28at.com

impl —实现在另一个包里TvI28资讯网——每日最新资讯28at.com

  • ServiceImpl2
  • impl2 —新实现在另一个包里TvI28资讯网——每日最新资讯28at.com

  • DaoTvI28资讯网——每日最新资讯28at.com

其次,调整打包配置,ServiceImpl 和 ServiceImpl2 二选一。既然 ServiceImpl 和 ServiceImpl2 是二选一,那 ServiceImpl 和ServiceImpl2 的包结构就可以相同。包结构相同了,那调整了依赖以后,依赖注入相关的配置就不需要调整了。调整后,项目结构看起来像这样:TvI28资讯网——每日最新资讯28at.com

  • Controller
  • Service — 接口模块

ServiceImplTvI28资讯网——每日最新资讯28at.com

impl —实现在另一个包TvI28资讯网——每日最新资讯28at.com

  • ServiceImpl2
  • impl —新实现和老实现在相同的包中TvI28资讯网——每日最新资讯28at.com

  • DaoTvI28资讯网——每日最新资讯28at.com

现在,ServiceImpl 和 ServiceImpl2 模块中的包结构、类名都是一样的。那我们还需要接口模块吗?TvI28资讯网——每日最新资讯28at.com

假设,我们把Service接口模块去掉,结构变成了如下所示:TvI28资讯网——每日最新资讯28at.com

  • Controller
  • Service1 — 老实现
  • Service2 — 新实现
  • Dao

单纯的通过调整模块依赖,是否能实现 Service 的多实现?答案显而易见吧?TvI28资讯网——每日最新资讯28at.com

上面给出了不使用接口的理由。不过不使用接口并不是完全没有缺点的,主要问题就是在进行多实现的时候,没有一个强接口规范。即不能通过实现接口,借助 IDE 快速生成框架代码。对于没有实现的接口,IDE 也能给出错误提醒。TvI28资讯网——每日最新资讯28at.com

一个不太优雅的解决是,将原来的模块里的代码拷贝一份到新模块中,基于老代码来实现新的逻辑。TvI28资讯网——每日最新资讯28at.com

所以,如果一个项目需要多实现、且多实现数量较多(不过一般项目不会有多个实现的),则推荐使用接口。否则不需要使用接口。TvI28资讯网——每日最新资讯28at.com

本文针对「Service 层是否需要接口」这个问题,指出需要接口的理由的问题。以及个人对这个问题的观点,希望在评论区写出自己的理解 !TvI28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-86980-0.html分层设计:Service 层真的需要实现接口吗?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Google 如果把 Go 团队给裁了会怎么样?

下一篇: 基于Spring Boot 3.x与Flowable的顺序会签模式实践

标签:
  • 热门焦点
  • Mate60手机壳曝光 致敬自己的经典设计

    8月3日消息,今天下午博主数码闲聊站带来了华为Mate60的第三方手机壳图,可以让我们在真机发布之前看看这款华为全新旗舰的大致轮廓。从曝光的图片看,Mate 60背后摄像头面积依然
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • 帅气纯真少年!日本最帅初中生选美冠军出炉

    日本第一帅哥初一生选美大赛冠军现已正式出炉,冠军是来自千叶县的宗田悠良。日本一直热衷于各种选美大赛,从“最美JK”起到“最美女星&r
  • 分布式系统中的CAP理论,面试必问,你理解了嘛?

    对于刚刚接触分布式系统的小伙伴们来说,一提起分布式系统,就感觉高大上,深不可测。而且看了很多书和视频还是一脸懵逼。这篇文章主要使用大白话的方式,带你理解一下分布式系统
  • 三言两语说透柯里化和反柯里化

    JavaScript中的柯里化(Currying)和反柯里化(Uncurrying)是两种很有用的技术,可以帮助我们写出更加优雅、泛用的函数。本文将首先介绍柯里化和反柯里化的概念、实现原理和应用
  • 消费结构调整丨巨头低价博弈,拼多多还卷得动吗?

    来源:征探财经作者:陈香羽随着流量红利的退潮,电商的存量博弈越来越明显。曾经主攻中高端与品质的淘宝天猫、京东重拾“低价”口号。而过去与他们错位竞争的拼多多,靠
  • ESG的面子与里子

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之三伏大幕拉起,各地高温预警不绝,但处于厄尔尼诺大“烤”之下的除了众生,还有各大企业发布的ESG报告。ESG是“环境保
  • 由于成本持续增加,笔记本产品价格预计将明显上涨

    根据知情人士透露,由于材料、物流等成本持续增加,笔记本产品价格预计将在2021年下半年有明显上涨。进入6月下旬以来,全球半导体芯片缺货情况加剧,显卡、处理器
  • 中关村论坛11月25日开幕,15位诺奖级大咖将发表演讲

    11月18日,记者从2022中关村论坛新闻发布会上获悉,中关村论坛将于11月25至30日在京举行。本届中关村论坛由科学技术部、国家发展改革委、工业和信息化部、国务
Top