在领域模型对象中使用工厂?

4

场景:

在我的应用程序中(它利用了一个丰富的领域模型,其中逻辑在模型中而不是服务中),我有用户。我使用服务创建新用户。

User newUser = userService.createNewUser("Hans Dampf");

或从数据库中获取它们

User oldUser = userDao.findByName("Hans Dampf");

因为在我的应用程序中,每次调用都可以直接访问用户对象,所以我希望将用户对象作为进入我的领域模型的入口点。
每个用户可以拥有不同类型的图库,保存在另一个表中。
class User {
 @OneToMany(fetch = FetchType.LAZY)
 @JoinColumn(name = "userId")
 private Set<Gallery> automatic = new HashSet<Gallery>();
}

我希望有一种简单的方法来启用特定的画廊。因此,我的API应该如下所示:

User user = ... // creating or retriving user
user.enableMainGallery();

在这个方法中,需要创建一个新的相册对象并将其添加到相册列表中。但是如何创建这个新实例?使用工厂模式吗?这将需要将工厂注入到域对象中(可能会有问题)。
public void enableAutomaticGallery() {
    automatic.add(automaticFactory.createAutomaticGallery(this));
}

还是我的接口定义有问题吗?我应该用其他方式定义它,这样我就不必注入工厂了吗?怎么做?


在这篇文章中http://evan.bottch.com/2007/12/06/factory-and-repository-in-the-domain/,它谈论了工厂和DAO是领域模型的一部分,我们不应将其视为应用级对象。我还不确定我的立场在哪里,但这是另一个观点。 - Edward Huynh
2个回答

1

正如你所说,域对象不应该依赖于应用程序级别的对象,例如工厂或Daos。

域通常是:

  • 足够复杂,具有功能需求,而不添加其他关注点(如持久性、验证、GUI等)
  • 中心化并且在各处使用(因此它的复杂性会损害您在许多编码活动中的生产力)
  • 可重用于相关应用程序,并在所有层中使用,甚至可以序列化并发送到客户端或WebService上的不同JVM(除非它依赖于应用程序级别的对象)

因此,您的enableAutomaticGallery方法应该在服务对象上。 它可以具有相同的代码,但将与应用程序相关。


但这会导致贫血的领域模型,不是吗?我必须暴露画廊集合和逻辑将在对象外部。或者我忽略了什么? - Arne Deutsch
@Arne 平衡有时很难找到,我曾经像你一样严格地遵循面向对象的思想,不想将关注点分散到多个类中。但是,领域非常复杂,每个开发人员都必须理解其重要性,并且所有关注点都可能添加大量代码,因此我发现这种做法不切实际。现在我的领域是我的代码中心,用注释(用于持久化、验证等)进行装饰。关注点是不同的代码,可以是单独的类(DAO、服务、GUI相关)或技术代码(触发器验证)。 - KLE
2
存在服务层并不会导致领域模型贫血。只有当应用程序中的所有逻辑都最终出现在服务中,而领域模型仅包含状态时,才会变得“贫血”。记住,面向对象编程的整个重点是将行为(方法)和状态(字段)合并到单个工件(类)中。但是,在领域中协调对象之间的活动方面拥有服务层是非常合理的。 - cliff.meyers

1

你的领域模型不应该知道任何服务、DAO层甚至是任何工厂对象。

我建议你不要使用一个需要将Gallery对象添加到实例集合中的方法User.enableMainGallery(),而是暴露一个方法User.addGallery(Gallery)

这样,负责“启用画廊”的类通过向列表集合中添加对象来完成此操作。

换句话说,我认为User对象不应该负责知道“启用主画廊”意味着什么。这听起来像是业务逻辑(一个模糊的术语,我知道)的一部分。


这一开始看起来很有前途,似乎是一个不错的答案。但是它能够良好地扩展吗?我想添加一个类型为“OldGallery”的图库,并需要将其升级为“NewGallery”。在我的设计中,这将导致一个方法“User.upgradeGallery(x)”(我同意用户类似乎有太多的职责)。但是如果用户只管理集合,那么逻辑又在模型之外了!我会有一个“GalleryService”,它会从用户中删除旧的图库并添加新的图库! - Arne Deutsch
1
在我个人看来,“领域模型”不应该包含像“为此用户添加画廊”或“将旧画廊升级为新画廊”之类的逻辑。有些人可能会称之为“贫血模型”——我对这个论点并不是很熟悉。我更喜欢将这种逻辑放在一个单独的层中,这样模型就可以纯粹地成为“模型”。 - matt b
好的...但是模型应该包含什么样的逻辑? - Arne Deutsch
1
您的数据以及它们之间的关系。 - matt b

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接