5

我正在设计一个具有特定模式的 API,但不知道该模式是否有名称。它类似于 GoF(四人组)中的命令模式,但不完全一样。

我可以找到的一个简单示例是在 Eclipse 中,您可以在其中操作项目 ( IProject),而不是通过调用项目上更改其状态的方法,而是通过以下 3 步过程:

  1. 将其状态提取到描述符对象 ( IProjectDescription) 中getDescription
  2. 在描述符上设置属性。例如setName
  3. 描述符应用回原始项目setDescription

一般原则似乎是你有一个复杂的对象作为具有许多潜在相互依赖的属性的框架的一部分,而不是直接处理该对象,一次一个属性,你将属性提取到一个简单的数据对象中,操纵它, 并将其应用回来。

它具有命令模式的一些属性,因为数据对象像命令一样封装了所有更改 - 但它不是真正的命令,因为您不会在对象上执行它,它只是表示对象的状态。

它还具有事务 API 的一些属性,通过set...调用一次完成所有更改,如果任何一个属性更改失败,您允许整个修改有效地“回滚”。但是,虽然这是该方法的一个优势,但这并不是它的真正主要目的。更重要的是,您可以在没有这种方法的情况下实现事务性质,只需将事务方法添加到 API(如commitrollback

我确实想利用这种模式有两个优点 - 尽管我没有看到它们被上面的 eclipse 示例利用:

  1. 您可以在底层对象的实现发生变化时表示其有意义的状态。这对于升级或从不同类型的表示复制状态很有用。假设我发布了一个新版本的 API,我在其中创建了一个对象 Foo2,它是我的旧 Foo1 的全新形式,但两者具有相同的基本属性。要将 Foo1 升级为 Foo2,我可以将这些属性提取为 FooState。foo2.setFooState(foo1.getFooState) 就这么简单。解释和表示属性的方式封装在 Foos 中,并且可以完全不同。

  2. 我可以使用我的简单数据对象来持久化和传输底层对象的状态,而持久化对象本身会复杂得多。因此,我可以将 Foo 的状态提取为 FooState,并将其作为简单的 XML 文档保存,然后通过“加载”并应用它来将其应用到某个新对象。或者我可以将 FooState 作为 JSON 对象简单地传输到 Web 服务,而 Foo 本身太大且太复杂而无法传输。(或者服务调用两端的对象完全不同,比如Foo1和Foo2)

无论如何,我在任何地方都找不到这种模式的名称或示例,无论是在四人组设计模式中,还是在 Martin Fowler 的综合“bliki”中

4

2 回答 2

3

Martin Fowler 在他的《企业应用程序架构原理》一书中描述的数据传输对象(DTO)似乎是为了您在第 2 点中描述的目的。

DTO 是对它所代表的更复杂的领域模型的相当简单的提取。

Fowler 描述了将 DTO 与汇编器结合使用可以使 DTO 独立于它应该表示的实际域对象(或对象)。汇编器知道如何从域对象创建 DTO,反之亦然。他还提到 DTO 需要可序列化以保持/传输其状态。您在第 2 点中描述的内容似乎与此描述相符。

您在第 1 点中描述的内容似乎不是预期目的,但使用此模式似乎绝对可以实现。

我不确定您是否浏览了他的书的 Pattern 目录或书本身。本书本身更详细地描述了这一点。

您可能还想查看来自 Oracle 的传输对象定义,Fowler 在这里说就是他所描述的 DTO。

于 2013-02-01T01:04:13.097 回答
2

并非每个设计都记录为单个设计模式,实际上大多数系统设计都是多种模式的组合。

但是,您正在做的其中一部分是使用 IProjectDescription 使用Memento,但是您的似乎是多态变体。将出现在模式目录中的模式视为基本起点而不是最终结果。模式在本质上应该被扩展和组合。

命令模式可以为您提供Commit 和 RollBack(Do/Undo),并以这种方式将其与 Memento 结合是一种非常常见的方法。在带有 HttpRequest 和 HttpResponse 的 Java Servlet API 中也可以看到同样的情况。

于 2013-01-25T14:08:50.610 回答