上下文您正在设计一个分布式应用程序,为了满足单个客户端请求,您发现自己对一个远程接口发出了多个调用,而这些调用所增加的响应时间超出了可接受的程度。
问题
如何保留过程调用接口的简单语义,而不受远程通信固有的滞后时间问题的影响? 影响因素在与远程对象通信时,请考虑下列需要权衡的因素:
解决方案创建一个数据传输对象 (DTO),用该对象包含远程调用所需要的所有数据。修改远程方法签名,以便将 DTO 作为单个参数接受,并将单个 DTO 参数返回给客户端。在调用方应用程序收到 DTO 并将其作为本地对象存储之后,应用程序可以分别对 DTO 发出一系列单独的过程调用,而不会引发远程调用开销。Martin Fowler 在 Patterns of Enterprise Application Architecture [Fowler03] 中对此模式进行了说明。 下图显示客户端应用程序如何进行一系列远程调用以检索客户名称的各个元素。 ![]() 图 1:没有 DTO 的远程调用 DTO 允许远程对象在单个远程调用中将整个客户名称返回给客户端。在此示例中,这样做将使调用次数从 4 次减为 1 次。客户端进行单个调用,然后在本地与 DTO 交互,而不用进行多次远程调用(见图 2)。 ![]() 图 2:通过使用 DTO 减少调用次数 DTO 是一组需要跨进程或网络边界传输的聚合数据的简单容器。它不应该包含业务逻辑,并将其行为限制为诸如内部一致性检查和基本验证之类的活动。注意,不要因实现这些方法而导致 DTO 依赖于任何新类。 在设计数据传输对象时,您有两种主要选择:使用一般集合;或使用显式的 getter 和 setter 方法创建自定义对象。 一般集合的优点是,只需要一个类,就可以在整个应用程序中满足任何数据传输目的。此外,集合类(例如,简单数组或散列图)内置于几乎所有语言库中,因此您根本不必编写新类的代码。对 DTO 使用集合对象的主要缺点是,客户端必须按位置序号(在简单数组的情况下)或元素名称(在键控集合的情况下)访问集合内的字段。此外,集合存储的是同一类型(通常是最一般的 Object 类型)的项目,这可以导致在编译时无法检测到的微妙但致命的编码错误。 如果为每个 DTO 创建自定义类,则可以提供与任何其他对象完全一样的、客户端应用程序可访问的强类型对象,这样的对象可以提供编译时检查,并支持代码编辑器功能(如 Microsoft® IntelliSense® 技术)。主要缺点是,如果应用程序发出许多远程调用,则您最终可能必须编写大量类的代码。 许多方法试图将这两种方法的优点结合在一起。第一种方法是代码生成技术,该技术可以生成脱离现有元数据(如可扩展标记语言 (XML) 架构)的自定义 DTO 类的源代码。第二种方法是提供更强大的集合,尽管它是一般的集合,但它将关系和数据类型信息与原始数据存储在一起。Microsoft ADO.NET DataSet 支持这两种方法(请参阅在 .NET 中使用 DataSet 实现 Data Transfer Object)。 有了 DTO 类以后,需要用数据填充它。大多数情况下,DTO 内的数据来自多个域对象。因为 DTO 没有行为,因此它不能从域对象提取数据。这是对的,因为如果让 DTO 不知道域对象,您就可以在不同的上下文中重用 DTO。同样,您不希望域对象知道 DTO,因为这可能意味着更改 DTO 将要求更改域逻辑中的代码,这将导致大量维护任务。 最佳的解决方案是使用 Assembler 模式 [Fowler03],该模式可以用业务对象创建 DTO 或者相反。Assembler 是 Mapper 模式的专门实例,在 Patterns of Enterprise Application Architecture [Fowler03] 中也提到过它。 ![]() 图 3:使用 Assembler 将数据加载到 DTO 中 Assembler 的关键特征是 DTO 和域对象不相互依赖。这就消除了这两种对象的相互影响。不利方面是 Assembler 同时依赖于 DTO 和域对象。对这些类的任何更改都可能导致必须更改 Assembler 类。 DTO 是简单对象,它不应该包含需要测试的任何业务逻辑。但是,您确实需要测试每个 DTO 的数据聚合。每个 DTO 可能需要测试,也可能不需要,这取决于您的序列化机制。如果序列化是框架的一部分,则只需要测试一个 DTO。如果不是这样,请使用一般的反射机制,这样就不需要测试每个 DTO 的序列化。 DTO 还对远程函数的可测试性有好处。通过使远程方法的结果能够在对象实例中使用,可以轻松地将此数据传递到测试模块,或将其与所需结果进行比较。 安全考虑事项理想情况下,应该先筛选和验证从不可靠的来源获得的数据(如来自 Web 页的用户输入),然后将其置于 DTO 中。通过这样做,就可以认为 DTO 中的数据是相对安全的,从而简化了将来与 DTO 的交互。 接收 DTO 的进程和关联用户的安全凭据也是值得注意的。DTO 通常包含从许多不同来源聚集在一起的大量信息。您是否已授权 DTO 的所有用户访问 DTO 所包含的所有信息?确保用户已得到授权的最佳方法是仅使用用户安全凭据所允许的特定数据填充 DTO。努力避免让 DTO 负责自己的安全性。这将增加 DTO 对其他类的依赖数,这意味着必须将这些类部署到使用 DTO 的所有节点。这还会将安全性功能分散到更多类中,从而增大了安全风险,并对灵活性和可维护性产生负面影响。 结果上下文Data Transfer Object 具有下列优缺点: 优点
缺点
相关模式
|
java中DTO与DAO的问题
最新推荐文章于 2024-06-26 11:02:34 发布
什么是DTO
2007-02-09 15:42