贫血模型与充血模型

2023-10-11 22:34
文章标签 模型 充血 贫血

本文主要是介绍贫血模型与充血模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们先了解一下事物脚本和领域模型的概念。
事物脚本: 事务脚本的核心是过程,通过过程的调用来组织业务逻辑,每个过程处理来自表现层的单个请求。大部分业务应用都可以被看成一系列事务,从某种程度上来说,通过事务脚本处理业务,就像执行一条条Sql语句来实现数据库信息的处理。事务脚本把业务逻辑组织成单个过程,在过程中直接调用数据库,业务逻辑在服务(Service)层处理。

领域模型: 领域模型的特点也比较明显, 属于面向对象设计,领域模型具备自己的属性行为状态,并与现实世界的业务对象相映射。各类具备明确的职责划分,领域对象元素之间通过聚合和引用等关系配合解决实际业务应用和规则。可复用,可维护,易扩展,可以采用合适的设计模型进行详细设计。缺点是相对复杂,要求设计人员有良好的抽象能力。

大家很奇怪吧,标题不是“贫血模型与充血模型的对比”吗,怎么扯到事物脚本和领域模型上了呢。我是这样理解的:在面向事物脚本编程中所使用的对象就是我们今天的主角之一“贫血模型”,当然领域模型自然也就对应着“充血模型”。那么他们最大的区别在哪里呢?其实Marth Folwer的贫血模型一文中已明确说明贫血模型是一种反模式,它根本就不是面向对象的产物,违反面向对象的核心思想,而充血模型则契合面向对象的思想。换句话说,贫血模型中只有属性,不存在领域操作,仅仅是被当做一种数据结构来使用。而充血模型有血有肉,既有属性,又有领域操作,贯彻面向对象的思想。啰嗦了…

又想起来一点,在阅读池建强老师在infoq上的领域驱动设计和实践与《领域驱动设计-软件核心复杂性应对之道》一书过程中才恍然大悟到:运用面向对象语言不一定编写出来的就是面向对象的程序。然觉悟到,原来从开始到现在所编写的程序统统与面向对象有出入,乃纯粹的面向事物脚本或者说面向过程化编程。

言归正传,首先我们从使用贫血模型与使用充血模型编程时,各自分包的特点。

贫血模型的包结构,如下图:
在这里插入图片描述

这个结构是我在实际开发中使用的,大家看着是否有熟悉的感觉!解释起来也很轻松,entity自然就是放实体(也就是贫血模型聚居地),dao自然是与数据库或其他持久策略交互的地方,service作为整个应用的核心,负责处理所有的逻辑,处理完成后交给dao做持久,controller起到调度的作用,其实就是一个个servlet。嘿嘿,熟悉吧,MVC模式。

《领域驱动设计》中建议的,使用充血模型时的包结构(更准确的说是DDD的包结构),如下图:
在这里插入图片描述

这个解释起来就比上一个要费劲很多,用两幅借来的图解释。 图中就是DDD中的四层结构,交互关系如下图:

在这里插入图片描述

四层的职责分配:
在这里插入图片描述

其中值得注意的地方是,应用的核心是领域层。

呀,说了好多,也不知道大家是否能理解,估计看到这里都厌烦了吧。

稍微总结一下:我的体会是,贫血模型与充血模型之间的差别一定程度上造成了面向过程化编程和面向对象编程的两个分支。那么差别到底是什么呢?说起来很简单,就是业务逻辑由谁去处理。贫血模型仅仅被当做数据结构来使用,而充血模型会持有业务逻辑方法。

其次我们通过一个例子,展现一个贫血模型与充血模型中显而易见的差别。 场景:一个网上银行的简单示例,要求可以存钱、取钱、转账、操作成功后需发送邮件给持卡人。要求提供贫血模型和充血模型两种实现方式。(例子不是那么恰当,网银怎么取钱、存钱啊,只为说明问题。)

首先我们看下贫血模型是如何实现的。

类图如下:

在这里插入图片描述

转账序列图如下:

在这里插入图片描述

在交互的过程中,你会发现,核心确实是service层。

其他部分都省略,在图中也能看个究竟,只贴出Account.java的代码:

public class Account implements Serializable {

private static final long serialVersionUID = 2248636870918341727L;private String accountNum;
private int totalAcount;
private String name;
private String cardNum;//此处省略get、set方法

  • 充血模型的实现

类图如下:

在这里插入图片描述

转账序列图:

在这里插入图片描述

同样贴出Account.java:

public class Account implements Serializable {

private static final long serialVersionUID = -4767597926507768285L;private AccountRepository accountRepository;private String accountNum;
private int totalAcount;
private String name;
private String cardNum;public void deposit(int mony){if(mony <= 0)return;this.totalAcount = this.totalAcount + mony;accountRepository.updateAccount(this);
}public void withdrawal(int mony){if(mony <= 0)return;if(mony > this.totalAcount)return;this.totalAcount = this.totalAcount - mony;accountRepository.updateAccount(this);
}

  • 不知道大家看出来区别了没有,充血模型是有血有肉的,核心领域方法都放到模型去去,而不是把领域方法放到模型之上的service层中去。

引用别人对贫血模型和充血模型的总结(没记错的话应该是javaeye的robbin总结的):

对于Java来说,更加适合采用贫血的模型,Java比较适合于把一个复杂的业务逻辑分离到n个小对象中去,每个小对象描述单一的职责,n个对象 互相协作来表达一个复杂的业务逻辑,这n个对象之间的依赖和协作需要通过外部的容器例如IoC来显式的管理。但对于每个具体的对象来说,他们毫无疑问是贫 血的。

这种贫血的模型好处是:

1、每个贫血对象职责单一,所以模块解藕程度很高,有利于错误的隔离。

2、非常重要的是,这种模型非常适合于软件外包和大规模软件团队的协作。每个编程个体只需要负责单一职责的小对象模块编写,不会互相影响。

贫血模型的坏处是:

1、由于对象状态和行为分离,所以一个完整的业务逻辑的描述不能够在一个类当中完成,而是一组互相协作的类共同完成的。因此可复用的颗粒度比较 小,代码量膨胀的很厉害,最重要的是业务逻辑的描述能力比较差,一个稍微复杂的业务逻辑,就需要太多类和太多代码去表达(针对我们假定的这个简单的工时管 理系统的业务逻辑实现,ruby使用了50行代码,但Java至少要上千行代码)。

2、对象协作依赖于外部容器的组装,因此裸写代码是不可能的了,必须借助于外部的IoC容器。

对于Ruby来说,更加适合充血模型。因为ruby语言的表达能力非常强大,现在用ruby做企业应用的DSL是一个很热门的领域,DSL说白了就是用来描述某个行业业务逻辑的专用语言。

充血模型的好处是:

1、对象自洽程度很高,表达能力很强,因此非常适合于复杂的企业业务逻辑的实现,以及可复用程度比较高。

2、不必依赖外部容器的组装,所以RoR没有IoC的概念。

充血模型的坏处是:

1、对象高度自洽的结果是不利于大规模团队分工协作。一个编程个体至少要完成一个完整业务逻辑的功能。对于单个完整业务逻辑,无法再细分下去了。

2、随着业务逻辑的变动,领域模型可能会处于比较频繁的变动状态中,领域模型不够稳定也会带来web层代码频繁变动。

好像在里面掺杂了好多东西,如果大家觉得罗嗦,可以看看这篇讲领域模型的文章,比我写的好,哈哈。链接在此:http://www.blogjava.net/GandofYan/archive/2006/05/30/48954.html

其实仅仅就这个例子的两种实现,还有太多太多的东西要去讲,但不是本篇的重点。学海无涯啊,领域驱动设计这方面的文章,在看书的过程中有任何感悟时我会陆续发到社区中。

参考资料:http://www.infoq.com/cn/articles/cjq-ddd

这篇关于贫血模型与充血模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/191297

相关文章

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

AI Toolkit + H100 GPU,一小时内微调最新热门文生图模型 FLUX

上个月,FLUX 席卷了互联网,这并非没有原因。他们声称优于 DALLE 3、Ideogram 和 Stable Diffusion 3 等模型,而这一点已被证明是有依据的。随着越来越多的流行图像生成工具(如 Stable Diffusion Web UI Forge 和 ComyUI)开始支持这些模型,FLUX 在 Stable Diffusion 领域的扩展将会持续下去。 自 FLU

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者