Service层在MVC框架中的意义和职责
https://blog.csdn.net/u012562943/article/details/53462157
mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面。
mvc模式是web开发中的基础模式,采用的是分层设计,各层之间职责分明。然而事与愿违,当我们日积月累的基于mvc模式开发之后,会逐渐的感受到层与层之间存在粘连和职责模棱两可的地方,这就是service层出现的重要原因。
问题是什么
要提出解决方案,重要的是发现问题的本质。mvc模式在实践过程中,主要面临下面几个难受的问题:
在C层直接实现业务逻辑,这将导致:
不同的controller之间,无法共享通用的业务逻辑,比如:折扣计算,反作弊判定,这必然是不合理的。
业务逻辑升级,需直接在原代码上做修改兼容,导致controller代码不断膨胀复杂。
远程服务协议或者调用方式升级,需要找到所有controller里的调用点,逐一修改。
DAO发生替换(比如从oracle迁移mysql),需要找到所有controller里的调用点,逐一修改。
在M层(DAO+model或者ActiveRecord,下面以model泛指)里实现业务逻辑,这将导致:
model承担了过多的业务逻辑,导致业务逻辑升级需要修改model,然而model的职责并不是业务,这是很矛盾的。
调用1个model中的业务代码没有问题,但是遇到跨表事务又该由哪个model管理呢?
业务逻辑实现在model中,如果model发生变更,那么里面写的业务逻辑也得粘贴复制到新的model中,这就是耦合的代价。
我仔细的回想了一下之前的MVC开发模式,上面的问题我几乎都遇到过并且试图解决过,比如:
为了提升代码复用,我会把一些通用的功能实现为单独的工具类(校验登录),并在controller中提供调用。
为了给controller提供业务相关的数据,我在ActiveRecord里实现了业务相关的增删改查方法供controller调用,更有意思的是:每次表变更字段,我通过工具gii重新生成ActiveRecord都会把我实现的方法覆盖,这就是耦合的代价。
问题的本质是:业务逻辑粘连了C层和M层,应该从C层&M层解耦出来,成为独立的Service层。由此,在C层可以灵活的替换Service保持高度的简洁,而M层保持职责单一仅仅为Service提供数据,Service层则实现所有复杂的业务逻辑与通用的业务逻辑。
Service层的职责
根据上面的分析,Service夹在C层和M层中间,从逻辑上大致划分为3大类:
model侧的Service:也就是封装每个model与业务相关的通用数据接口,比如:查询订单。(我认为:访问远程服务获取数据也应该归属于这一类Service)
中间的Service:封装通用的业务逻辑,比如:计算订单折扣(会用到1中的Service)。
controller侧的Service:基于1、2中的Service进一步封装对外接口的用户业务逻辑,当然也不排斥直接访问DAO而不使用上述2个Service(不建议)。
在实践中,应该会很自然的用到这三类Service,在了解了这些概念之后再进行代码设计,就不会对Service的职责产生困惑了,自然也对MVC有了新的认识。
关于抽象
Controller里调用"controller侧的Service"直接完成业务处理,意味着Controller依赖了具体是哪个Service类。
Service里调用"DAO/AR"实现数据库的访问,意味着Service依赖了具体是拿个"DAO/AR"类。
Service里调用Service,意味着Service依赖了具体是拿个Service类。
为了解除这种耦合,在Web领域一般采用的都是IOC依赖注入来实现"依赖反转",JAVA和PHP都可以基于反射实现这个能力,各个mvc框架都有相似的实现。
Service层是否必要呢?
见仁见智,我认为长时间维护的大型项目通过更精细的分层,更加有利于功能的迭代升级。
而对于中小项目,多一层就意味着更多的代码,而且在设计时还要考虑通用性以及通用性的粒度问题,还不如少动点脑子多写点冗余代码了。
Service层在MVC框架中的意义和职责的更多相关文章
- 谈谈service层在mvc框架中的意义和职责
mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面. mvc模式是web开发中的基础模式,采用的是分层设计, ...
- Java Web学习总结(30)——Service层在MVC框架中的意义和职责
mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面. mvc模式是web开发中的基础模式,采用的是分层设计, ...
- [原]命令模式在MVC框架中的应用
其实在项目开发中,我们使用了大量的设计模式,只是这些设计模式都封装在框架中了,如果你想要不仅仅局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之一就是命令模式,先来看看模式是如何 ...
- 命令模式在MVC框架中的应用
事实上在项目开发中,我们使用了大量的设计模式,不过这些设计模式都封装在框架中了,假设你想要不只局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之中的一个就是命令模式,先来看看模式 ...
- 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。前端控制器既可以使用Filter实现(Struts2采用这种方式),也可以使用Servlet来实现(spring MVC框架)。
本文转自http://www.cnblogs.com/davidwang456/p/4090058.html 感谢作者 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并 ...
- 找到MVC框架中前端URL与后端同步的解决方案
基本思路: 先用URL标签生成完整的URL字符,前端动态参数的部分以适配符先填充,最后动态参数利用正则匹配进行替换. 这种方式,可以在各种MVC框架中适用,妙. 不废话,上码. var url = & ...
- asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析
下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...
- 在ASP.NET MVC 框架中调用 html文件及解析get请求中的参数值
在ASP.NET MVC 框架中调用 html文件: public ActionResult Index() { using (StreamReader sr = new StreamReader(P ...
- MVC框架中的值提供机制(三)
在MVC框架中NameValueCollectionValueProvider采用一个NameValueCollection作为数据源,DictionnaryValueProvider的数据源类型自然 ...
随机推荐
- 三阶平面魔方(BFS)
有一个 3×3 的平面魔方,在平面魔方中,每个格子里分别无重复地写上 1 - 9 这 9 个数字.一共有 4 种对平面魔方的操作: 选择某一行左移. 选择某一行右移. 选择某一列上移. 选择某一列下 ...
- C++---类成员变量定义为引用
摘要:类成员变量是可以定义为引用类型的,但是我们需要注意一下用法 note1:在类中定义引用变量, 必须要在初始化列表中初始化该成员变量(const 类型数据成员也必须在初始化列表中进行初始化) #i ...
- Cutting Sticks UVA - 10003(DP 仍有不明白的地方)
题意:对一根长为l的木棒进行切割,给出n个切割点,每次切割的价值,等于需要切割的木头长度. 一开始理解错了,认为切割点时根据当前木条的左端点往右推算. 实际上,左端点始终是不变的一直是0,右端点一直是 ...
- 数据分析-Matplotlib:绘图和可视化
学习路线 简介 简单绘制线形图 plot函数 支持图类型 保存图表 1.简介 Matplotlib是一个强大的Python绘图和数据可视化的工具包.数据可视化也是我们数据分析的最重要的工作之一,可以帮 ...
- 【hdu6613】Squrirrel 树形DP
题意:给一个带权树,求把一条边的权值变成0,再选一个点做根,最大深度最小是多少. \(\sum n \le 10^6\) key:树形DP 题里有边权小于等于200,然而并没有什么用. 首先做出 \( ...
- debian8修改kde桌面语言
apt-get install kde-l10n-zhcn, language里面改中文 亲测可用 来源:http://tieba.baidu.com/p/2489771177
- ubuntu19.10——snap错误has install-snap change in progress
使用软件商店安装时遇到问题 snap has install-snap change in progress 原因是之前的安装错误终止,使得现在的安装无法进行,解决方案: 终端输入: snap cha ...
- vue 项目在scope中使用@import引入css ,作用域是全局
有时候引入第三ui插件,修改样式 时候,需要再单独定义style标签,才有效果,可是会影响全局影响全局,如下所示 加上/deep/,就可以了,
- python学习笔记(27)-unittest单元测试-测试用例
单元测试 #单元测试 #unittest+接口 unittest python自带 pytest+jenkins+allure #接口测试的本质 就是测试类里面的函数 #单元测试的本质 测试函数 代码 ...
- 谈谈有关 Python 的GIL 和 互斥锁
转载:https://blog.csdn.net/Amberdreams/article/details/81274217 有 Python 开发经验的人也许听说过这样一句话:Python 不能充分利 ...