0. 写在前面
首先,这是一篇翻译文章,个人建议你可以阅读英文原文Baeldung: The DTO Pattern (Data Transfer Object),因为个人水平,很多地方翻译的不通顺和晦涩,如果你选择继续往下看,请不要高估了我的英文水平。当然,你也可以对比原文来看。
1. 概览
在这篇教程中,我们将讨论 DTO 模式,它是什么,怎样以及何时使用它们。在最后,希望我们知道如何正确地使用它。
2. DTO模式
DTO 或者说数据传输对象(Data Transfer Objects)是在处理方法中携带数据的对象,**目的是减少方法调用的次数。**Martin Fowler 在他的书Patterns of Enterprise Application Architecture中第一次提出该模式。他解释说该模式的主要目的是通过将一次单一调用的多个参数分批来减少到服务器的往返次数。因而在这样的远程操作中降低网络开销。该实践的其它好处是序列化的逻辑(转换对象结构和数据为一种能被存储和传输的指定格式的机制)的封装。它提供了在序列化细微差别中一个单一改变点。它也解耦了表示层的领域模型,允许它们独自改变。
3. 怎样使用它
DTOs 一般被创建为 POJOs。它们是平整的数据结构,不包含业务逻辑,仅仅有存储、访问和最终关联序列化或解析的方法。数据从领域模型映射为 DTO,一般通过在表示层或门面层的 mapper 组件。下方的图片说明了组件间的交互:
4. 何时使用它
正如它的定义中提到的,DTO 在带有远程调用的系统中出现,因为它帮助减少了调用的次数。当领域模型有多种不同对象组成,并且表示层模型甚至一次需要它们的全部数据时,DTO 也能帮忙减少在客户端和服务器间的往返。使用 DTO,我们能从领域模型中构建不同的视角,允许我们创造相同域但优化它们为不影响域设计的客户端的需求的其它表示。这样的灵活性是一个解决复杂问题的强力工具。
5. 使用事例
为了展示这个模式的实现,我们将使用一个有两个主要领域模型的简单应用。在这个事例中,User
和Role
,为了专注于该模式,让我们看两个功能性的例子,获取用户和创建新用户。
5.1 DTO vs. Domain
下方定义了这两个模型:
public class User {
private String id;
private String name;
private String password;
private List<Role> roles;
public User(String name, String password, List<Role> roles) {
this.name = Objects.requireNonNull