为什么说基于贫血模型的MVC架构违背OOP

我们大部分的业务开发都是MVC架构的,但是我们平时使用的基于贫血模型的MVC架构它对吗?为了搞清楚这个问题,我们先来理清楚几个概念。

一、贫血模型VS充血模型

贫血模型与充血模型是软件开发中两种常见的设计模式,它们各自具有独特的特点和适用场景。

贫血模型,也被称为数据驱动模型,主要基于数据库的建模。在这种模型中,数据和操作被分离,数据对象主要存储数据,而操作则全部放在业务逻辑层中实现。领域对象通常只包含getter和setter方法,没有具体的行为,所有的业务逻辑都放在业务逻辑层处理。这种设计模式的优点在于使系统的层次结构清晰,各层之间单向依赖,有利于代码的清晰和可维护性,同时也提高了代码的可重用性和扩展性。然而,其缺点在于领域对象只是作为保存或传递状态使用,缺乏真正的对象行为,这在一定程度上降低了代码的面向对象性。

充血模型则基于对象的建模,通过面向对象的方式抽象系统关系。在充血模型中,领域模型不仅包含自身的属性状态,还包括方法行为等,即领域对象不仅包含数据,还包含对这些数据的操作。这使得领域模型更加生动和灵活,能够更好地反映真实世界的业务逻辑。充血模型的优点在于它更符合面向对象的理念,领域对象具有完整的生命周期和行为,这使得代码更加易于理解和维护。同时,由于业务逻辑和数据操作都在领域对象中,也提高了代码的内聚性。

综上所述,贫血模型和充血模型各有其优势和适用场景。在选择使用哪种模型时,需要根据项目的具体需求、团队的技术能力和维护成本等因素进行综合考虑。对于简单的业务场景,或者当领域对象的业务逻辑较为简单时,可以选择使用贫血模型;而对于复杂的业务场景,或者需要更好地体现面向对象特性的情况,充血模型可能更为合适。

可见我们平时使用的MVC模式,是面向过程的一种编程思维,但是由于历史原因和真实业务的情况,反而是基于贫血模型的MVC架构使用的更多。

二、MVC

MVC(Model-View-Controller)是一种软件设计模式,主要用于构建用户界面和应用程序的架构。MVC将应用程序的输入、处理和输出分开,使其更加易于管理和维护。MVC模式通过将应用程序分为三个主要组件来工作:模型(Model)、视图(View)和控制器(Controller)。

  1. 模型(Model)
    • 模型是应用程序的核心部分,代表应用程序的数据和业务逻辑。
    • 它负责数据的存储、检索和状态管理。
    • 模型不依赖于视图或控制器,这意味着模型可以被多个视图共享,并且可以独立于视图进行测试。
    • 模型通常包含数据访问逻辑,与数据库或其他数据源进行交互。
  2. 视图(View)
    • 视图是用户界面的表示,负责显示数据给用户。
    • 它从模型中获取数据,并将其以特定的格式(如HTML、JSON等)呈现给用户。
    • 视图通常是被动的,它等待控制器发送数据来更新其内容。
    • 视图不应该直接访问模型,它应该通过控制器来获取数据。
  3. 控制器(Controller)
    • 控制器是模型和视图之间的协调者。
    • 它接收用户的输入(如点击事件、表单提交等),并决定如何处理这些输入。
    • 控制器可能会从模型中获取数据,并发送给视图进行显示,或者根据用户的输入更新模型的状态。
    • 控制器确保模型和视图保持同步,并且负责响应用户请求。

MVC模式通过将应用程序的输入、处理和输出分离,使得代码更加模块化,提高了代码的可维护性和可重用性。当业务逻辑或用户界面需要改变时,只需要修改相应的组件,而不需要对整个应用程序进行大规模的修改。

MVC模式广泛应用于各种Web应用程序和桌面应用程序中,是软件开发中非常重要的一种设计模式。通过使用MVC模式,开发人员可以更好地组织和管理代码,提高应用程序的可扩展性和可维护性。

三、拓展问题(MVC模式中的Entity,bo,vo可以合并成一个类吗?)

在MVC(Model-View-Controller)模式中,EntityBO(Business Object)和VO(Value Object)通常各自具有特定的职责,不建议将它们合并成一个类。以下是它们各自的作用和为什么不建议合并的原因:

  1. Entity(实体)
    • 代表数据库中的一张表或数据模型。
    • 通常与数据库表字段一一对应,包含主键、外键等数据库相关的特性。
    • 负责数据的持久化,与数据库交互。
  2. BO(Business Object,业务对象)
    • 封装了业务逻辑,包含了与业务相关的属性和方法。
    • 通常用于处理复杂的业务逻辑,如计算、验证等。
    • 可能是由多个Entity组成的一个复合对象,或者对Entity进行了封装和扩展。
  3. VO(Value Object,值对象)
    • 主要用于数据的传输和展示,通常用于前后端之间的数据交换。
    • 只包含数据,不包含行为(方法)。
    • 可能是Entity的一个子集,或者是对Entity数据的重新组合和格式化。

为什么不建议合并它们

  • 职责分离:每个对象都有其特定的职责。将它们合并会导致一个对象承担过多的责任,使得代码难以理解和维护。
  • 耦合度增加:合并这些对象会增加它们之间的耦合度,使得修改其中一个对象可能影响到其他对象。这违反了“高内聚、低耦合”的软件设计原则。
  • 可重用性降低:如果合并成一个类,那么在不同的场景中(如不同的业务逻辑、不同的数据展示需求)使用这个类时,可能需要进行大量的条件判断和逻辑分支,降低了代码的可重用性。
  • 测试困难:合并后的类将包含多种不同的功能和逻辑,这使得对其进行单元测试变得更加困难。

在实际开发中,通常建议根据项目的具体需求和设计原则,合理地使用这些对象,并根据需要进行适当的封装和组合,以达到更好的代码质量和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/800662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何进行Python代码的调试和测试?

如何进行Python代码的调试和测试? Python代码的调试和测试是软件开发过程中不可或缺的一部分,它们确保代码的正确性、可靠性和性能。下面将详细讨论如何进行Python代码的调试和测试。 一、Python代码调试 调试是查找并修复代码错误的过程。Python提…

大学英语ab级题搜题软件?分享7个支持答案和解析的工具 #笔记#其他

合理利用学习辅助工具和资料,可以帮助大学生更好地组织学习内容、掌握知识点和提升学术水平。 1.智能翻译官 这是一款多语言在线翻译神器,除了最基础的英语以外,还支持日语、德语、俄语、法语等几十种语言文本翻译和拍照翻译,并…

面试算法-148-轮转数组

题目 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,…

php代码执行计划任务dos实现方式和宝塔面板实现方式

dos php 计划任务 echo off :loop echo 这是一个死循环 echo This is an infinite loop. php think gpt php think ai timeout /t 2 goto loop 宝塔面板 php 计划任务 #!/bin/bash PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH ste…

蓝桥杯刷题--python38

197. 阶乘分解 - AcWing题库 def init(n): for i in range(2,n1): if not st[i]:primes.append(i) j0 while primes[j]*i<n: st[i*primes[j]]1 if i%primes[j]0: break j1 nint(input(…

关于Ansible模块 ⑤

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 继《关于Ansible的模块 ①》、《关于Ansible的模块 ②》与《关于Ansible的模块 ③》之后&#xff0c;继续学习ansible常用模块之…

如何利用Flutter将应用成功上架至iOS平台:详细指南

引言 &#x1f680; Flutter作为一种跨平台的移动应用程序开发框架&#xff0c;为开发者提供了便利&#xff0c;使他们能够通过单一的代码库构建出高性能、高保真度的应用程序&#xff0c;同时支持Android和iOS两个平台。然而&#xff0c;完成Flutter应用程序的开发只是第一步…

医院要不要安装医疗设备漏费控费管理系统

19339904493&#xff08;康溪&#xff09; 不知道大家有没有去医院做过检查&#xff0c;比如说做B超、彩超、多普勒、胃肠镜、心电、脑电&#xff0c;核磁、CT、DR、X光、钼靶、生化分析仪、血球等。你们可能不知道&#xff0c;在做检查、检验的时候还会存在一个漏洞。医院的存…

Golang sync.Once 的作用

sync.Once的作用正是为了防止在多goroutine并发执行时&#xff0c;对某个操作进行重复的初始化。它确保即使在高度并发的场景下&#xff0c;某些高成本的初始化操作&#xff08;比如创建资源、加载配置、设置全局状态等&#xff09;也只会被执行一次。 比如进行下面的这个例子…

HarmonyOS NEXT应用开发之@Link装饰器:父子双向同步

子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 说明&#xff1a; 从API version 9开始&#xff0c;该装饰器支持在ArkTS卡片中使用。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 限制条件 Link装饰器不能在Entry装饰的自定义组件中使用…

Java常用API_时间

一&#xff0c;JDK7时间&#xff1a; 1.Date&#xff1a; 我先通过一段代码简单展示一下它的几个方法及功能 代码&#xff1a; 这里要注意的是 时间原点&#xff1a;1970年1月1日 00:00:00 中国的时间原点&#xff1a;由于中国处在东八区&#xff0c;时间原点要晚上8小时&…

MySQL 主从 AUTO_INCREMENT 不一致问题分析

本文介绍了 MySQL5.7 中常见的replace into 操作造成的主从auto_increment不一致现象&#xff0c;一旦触发了主从切换&#xff0c;业务的正常插入操作会触发主键冲突的报错提示。 一、问题描述 1.1 问题现象 在 MySQL 5.7 版本中&#xff0c;REPLACE INTO 操作在表存在自增主键…

状态机编程的常用框架和方法

状态机编程是一种管理复杂系统行为的有效方法&#xff0c;它通过定义一系列状态、事件、转换和动作来描述系统的行为。在嵌入式系统开发中&#xff0c;状态机编程尤为重要&#xff0c;因为它可以帮助开发者以结构化的方式处理系统中的并发和异步事件。以下是一些常用的状态机编…

大话设计模式——六大基本设计原则(SOLID原则)

设计模式 定义&#xff1a;软件开发中&#xff0c;在特定上下文中解决一类常见问题的被证明为有效的最佳实践。可供其他开发者重复使用解决相似问题。 好处&#xff1a; 提高代码的可重用性&#xff0c;减少重复代码。提高代码的可维护性&#xff0c;使代码更易于理解和修改。…

django怎么设置把logger.info的日志保存到本地文件

在Django项目中,要将logger.info()产生的日志信息保存到本地文件,需要对Django的logging配置进行设置。以下是一个详细的步骤说明和示例代码:步骤一:配置settings.py在Django项目的settings.py文件中,添加或更新LOGGING配置字典。这是一个标准的Python字典,遵循logging模…

nssm 工具把asp.net core mvc变成 windows服务,使用nginx反向代理访问

nssm工具的作用&#xff1a;把项目部署成Windows服务&#xff0c;可以在系统后台运行 1.创建一个asp.net core mvc的项目weblication1 asp.net core mvc项目要成为windows服务需要安装下面的nuget包 <ItemGroup><PackageReference Include"Microsoft.Extension…

Gradle系列(五)-常用的gradle命令

Gradle系列(五)-常用的gradle命令 本文主要记录下gradle下常用的命令 1: gradle -v gradle -v 命令可以获取Gradle的版本信息。 2: gradle dependencies gradle dependencies命令用于显示项目的依赖关系。它会列出项目中所有的依赖项&#xff0c;包括直接依赖和传递依赖. …

【LeetCode热题100】35. 搜索插入位置(二分)

一.题目要求 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 二.题目难度 简单 三.输入样例 示例 1: 输入: nums…

PgSQL的with as语法

returning 返回的这一些字段&#xff0c;然后进行汇总为remove_alarms 然后select一下remove_alarms 出来的数据然后保存到tb_alarm_his 里面 with remove_alarms as( delete fromtb_alarm whereid in (508) returning 0,now(),admin,alarmadvice,alarmadvicecn,alarmarises…

2_7.Linux中的无人值守安装脚本kickstart

## 一.kickstart自动安装脚本的作用 ## #在企业中安装多台操作系统时面临的问题# 当安装Linux操作系统时&#xff0c;安装过程会需要回答很多关于设定的问题 这些问题必须手动选择&#xff0c;否则无法进行安装 当只安装1台Linux系统&#xff0c;手动选择设定工作量比较轻松 当…