领域模型(DomainModel)与视图模型(ViewModel)
Model-View-Controller(模型-视图-控制器,MVC)模式将你的软件组织并分解成三个截然不同的角色:
- Model 封装了你的应用数据、应用流程和业务逻辑。
- View 从 Model 获取数据并格式化数据以进行显示。
- Controller 控制程序流程,接收输入,并把它们传递给 Model 和 View。
与其它设计模式不同,MVC 模式并没有直接反映一个你能够编写或配置的类结构。相反,MVC 更像一个概念上的指导原则或范型。概念上的 MVC 模式被描述为三个对象 —— Model、View 和 Controller —— 之间的关系。由于 View 和 Controller 都可以从 Model 请求数据,所以 Controller 和 View 都依赖 Model。任何输入都通过 Controller 进入你的系统,然后 Controller 选择一个 View 来发出结果。
Model 包含了你的应用逻辑和数据,在你的应用程序中,它很可能是主要的值驱动器。Model 没有任何与表现层相关的特性,而且也和 HTTP 请求处理职责中完全无关。
Domain Model 是一个对象层,是对现实世界逻辑、数据和你应用程序所处理的问题的抽象。
Domain Model 可分为两大类:Simple Domain Model 和 Rich Domain Model。
- Simple Domain Model 往往是业务对象和数据库表之间一对一的通信。你已经见过的几种模式 —— Active Record、Table Data Gateway,以及 Data Mapper,所有这些与数据库相关的设计模式 —— 可以帮助你把与数据库相关的逻辑组织成一个 Domain Model。
- Rich Domain Model 包含复杂的,使用继承机制紧密联系在一起的对象网络,在本书和 GoF 一书中介绍的众多模式起着杠杆作用。Rich Domain Models 往往是柔性的,精心测试过的,不断重构的,而且与它们所表达的领域所需的业务逻辑紧密耦合。
采用哪种 Domain Model 类型取决于你的应用环境。如果你正在建立的是一个非常简单的表单处理 web 应用,没必要建立 Rich Domain Model。然而,如果你正在编写一个价值数百万的企业内联网架构的核心库,那么努力开发一个 Rich Domain Model 就是值得的,它可以为你提供一个准确表达业务过程的平台,并可以让你快速传输数据。
Martin Fowler 在 PoEAA 中同时简要介绍了两种 Domain Model。而 Eric Evans 的 Domain Driven Design 一书,则完全专注于 Rich Domain Model 的实践应用和开发过程。
View 用于处理所有表现层方面的问题。View 从 Model 获取数据,并可以把它格式化成用于 web 页的 HTML,用于 web 服务的 XML,或用于 email 的文本。
许多的MVC模式的实现也都使用一个View Model或Application Model的概念,Controller是沟通的媒介,架起领域模型和用户界面之间的桥梁,属于表现层。为了View的简单性,Controller负责处理或者将领域模型转换成一个View Model,这通常叫做数据传输对象(DTO)。
DomainModel != ViewModel
DomainModel代表着相应的域,但ViewModel却是为View的需要而创建。这两者之间或许(一般情况下都)是不同的,此外DomainModel是数据加上行为的组合体,是由复杂的变量类型组成的并且具有层次。而ViewModel只是由一些String等简单变量类型组成。如果想移除冗余并且容易导致出错的ORM代码,可以使用AutoMapper.如果想要了解更多。
那么领域模型(Domain Model )和视图模型(View Model)有什么不同呢?
在ASP.NET MVC的应用程序中经常可以可以看到View Model,经常我们都认为领域模型和视图模型是同一个东西。这特别是把领域模型包含在数据传输对象DTO里的时候,例如使用Entity Framework之类的ORM工具生成的实体。在这种情况下,领域模型和视图模型包含的实体非常相似,都是一些简单的CRUD操作。
这些实体有许多属性,有相同或类似的名称,你可以很容易地映射领域实体对应视图模型中的一个属性。不过,这些相似的属性也可能略有不同,例如类型或者格式。例如,用户填写的用户界面的一个属性,他在视图模型里可能是一个“Nullable”的。
另一方面,领域实体可能需要一个经过验证的合法的值,所以需要一个在用户界面的领域模型之间的转换。另一个例子是,用户界面可能会显示一个滑块,用于用户选择多少天以后提交他的订单。在这种情况下,视图模型可能使用一个整数属性来表示,领域模型通常是一个日期值。
视图模型通常只包含领域模型的一个子集,而且只包含界面上所需要的属性。此外,视图模型可能是一个领域模型树的扁平版本,例如,一个Customer实体有一个Address,而这又是一个整体,它包含街道地址,邮政编码,国家等。一个Customer 视图模型用于显示数据,将地址数据拉平填充到视图模型类里。
此外如果一个View需要同时处理几个领域模型,View Model就是这几个Domain Model的总和。领域模型和视图模型之间有很多相似的地方,我们经常干脆就把Domain Model当作View Model来使用了。
上面讨论了领域模型和视图模型的相似性,我们来看看都有几种方式把领域模型转换为视图模型,通常有3种方法:
- 把领域模型当作视图模型来用,也就是领域模型就是视图模型,大部分都是这么用的。
- 视图模型里面包含一个领域模型,定义一个视图模型,里面包含了一个领域模型,通过属性方式进行访问。
- 将领域模型映射到视图模型,领域模型并没有直接映射到视图模型,需要处理这种映射关系。
我们不建议直接把领域模型实体暴露给视图,因为有许多细微之处,可能导致您混合业务和表示层的逻辑,无论是领域实体的属性显示还是业务的验证规则,这都是应用程序处理的不同方面。
直接将你的领域模型作为Conroller上的处理参数面临着安全风险,因为Controller或者Model binder必须确保属性验证和用户不能修改她自己不能修改的属性(例如,用户手动更新了一个隐藏的输入值,或增加一个额外的属性值,而这个并不是界面上的元素,但却正好领域模型实体的属性,这种风险叫做“over-posting”),即使对当前版本的领域模型做了正确的验证,领域模型将来可能做了变更修改,并没有出现编译错误或者警告,可能导致新的风险。
我们应当避免使用前两种方法将领域模型转换成视图模型,推荐使用第三种方法,定义单独的视图模型类。做这种领域模型到视图模型的转换工作是一种重复性的工作,已经有几个工具可以帮助你来完成这项工作。最常用的一个工具就是.NET 社区的开源项目AutoMapper。
(个人理解:针对域模型与视图模型,有时候需要看具体的业务场景,一般情况下可以按照上述将DomainModel和ViewModel进行数据映射,以避免一些安全性问题;但是也可以将DomainModel当成ViewModel来使用也是可以的,通过在系统实现、业务逻辑操作和判断上是可以保证业务安全性的。就是前者也要进行判断以保证安全性。所以,还是看具体业务系统的使用环境与要求来决定采用哪种方式来实现。)
文章转载自:http://www.cnblogs.com/shanyou/archive/2010/04/03/1703501.html
领域模型(DomainModel)与视图模型(ViewModel)的更多相关文章
- DDD:谈谈数据模型、领域模型、视图模型和命令模型
背景 一个类型可以充当多个角色,这个角色可以是显式的(实现了某个接口或基类),也可以是隐式的(承担的具体职责和上下文决定),本文就讨论四个角色:数据模型.领域模型.视图模型和命令模型. 四个角色 数据 ...
- 利刃 MVVMLight 2:Model、View、ViewModel结构以及全局视图模型注入器的说明
上一篇我们已经介绍了如何使用NuGet把MVVMLight应用到我们的WPF项目中.这篇我们来了解下一个基本的MVVMLight框架所必须的结构和运行模式. MVVMLight安装之后,我们 ...
- .NET:关于数据模型、领域模型和视图模型的一些思考
背景 数据模型.领域模型和视图模型是“模型”的三种角色,一些架构用一种类型表示这三种角色,如:传统三层架构.也有一些架构用两种类型表示这三种角色,如:结合ORM的领域驱动架构.非常少见的场景是用三种类 ...
- MVC无限级分类01,分层架构,引入缓存,完成领域模型与视图模型的映射
本系列将使用zTree来创建.编辑关于品牌.车系.车型的无限级分类,使用datagrid显示,源码在github.先上最终效果: datagrid显示所有记录.分页,提供添加.修改.删除按钮,并提供简 ...
- thinkphp 3.2 视图模型 实例 视图查询结果 二维数组 合并
使用视图模型查询的时候 结果是这样的 array(6) { [0] => array(5) { ["picTitle"] => string(7) "标题2& ...
- ThinkPHP 3.2.3 视图模型的使用
ThinkPHP 3.2.3 试图模型的手册地址是:http://www.kancloud.cn/manual/thinkphp/1781 实例 需求:在博客列表页读取博客的(id.标题.摘要.发布时 ...
- thinkphp 视图模型使用分析
<?php /** * 视图模型 * */ class ViewBatchModel extends ViewModel{ public $viewFields = array( 'Jinxia ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第三章:搜索、高级过滤和视图模型
在这一章中,我们首先添加一个搜索产品的模块以增强站点的功能,然后使用视图模型而不是ViewBag向视图传递复杂数据. 注意:如果你想按照本章的代码编写示例,你必须完成第二章或者直接从www.apres ...
- ThinkPHP第十六天(redirect、join、视图模型)
1.redirect /** * Action跳转(URL重定向) 支持指定模块和延时跳转 * access protected * @param string $url 跳转的URL表达式 * @p ...
随机推荐
- [转载] cassandra Unable to complete request: one or more nodes were unavailable
今天碰到的问题跟这个一模一样,特地转过来记录一下 https://support.datastax.com/hc/en-us/articles/204893189-CQL-query-results- ...
- Google 里的软件工程学
简评:原文作者 Fergus Henderson 在 Google 工作了 10 年以上,目前负责 Google 的 text-tospeech 工程小组.有很多书籍或文章会从 商业/管理 等非技术角 ...
- Oracle中ROWNUM的使用技巧
ROWNUM是一种伪列,它会根据返回记录生成一个序列化的数字.利用ROWNUM,我们可以生产一些原先难以实现的结果输出,但因为它是伪列的这个特殊性,我们在使用时也需要注意一些事项,不要掉入“陷阱”.下 ...
- http协议缓存小结
缓存可以使用expire方式,设置到期时间,缓存的时间等于expire设置的时间减去当前的时间 也可以使用no-cache的方式进行缓存,当设置了no-cache的方式时,以no-cache的为准,e ...
- JDK下载与安装、 Eclipse下载与使用的总结心得_20173311118_牛明旺
一.JDK下载与安装心得: ① 从官网http://www.oracl.com/technetwork/java上下载JDK,注意一定要同意该网站上的协议,否则下载不了(即点击“Accept Lic ...
- python科学计算与可视化
一.Numpy 库 NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. 引用: import ...
- BZOJ AC 300祭!
- 在微信移动端input file拍照或从相册选择照片后会自动刷新页面退回到一开始网站进入的页面
<input type="file" accept="image/*"/> 调用打开摄像头后,聚焦后拍照,点击确认,这时页面会出现刷新动作,然后回退 ...
- html5+js+.Net的即时多人聊天
今天看了下websocket的知识,了解到这是html5新增的特性,主要用于实时web的通信.之前客户端获取服务端的数据,是通过客户端发出请求,服务端进行响应的模式,或者通过ajax每 ...
- php7安装并apache
1.下载php7 选择THREAD SAFE版本,如果是64位系统要下载x64的,x86的不行 2.解压到想要安装的目录 3.apache配置 1) 添加PHP模块 查找“Dynamic Shared ...