代码之家  ›  专栏  ›  技术社区  ›  ken

在域对象方法中封装服务调用

  •  6
  • ken  · 技术社区  · 16 年前

    这是一个有效的对象设计吗? 我有一个域对象,在其中我注入一个服务并调用一个verify方法来更新对象的状态,如果一切顺利,则发送一条确认消息。代码如下所示:

    class Foo {
      String bar
      Service emailService
    
    
      public boolean verify() {
        bar = "foo"
            if(this.save()) {
                emailService.sendConfirmation()
            }
      }
    }
    
    Foo.get(1).verify()
    

    在这么远的地方给邮件服务打电话可以接受吗?有没有一个设计模式,我可以遵循这样的情况下使用。

    谢谢你 -肯

    3 回复  |  直到 16 年前
        1
  •  11
  •   Szymon Pobiega    16 年前

    从实体调用服务没有什么错。但是,在实例化这些服务时存在一些问题。如果遵循此路径,则必须在实体创建期间以某种方式获取服务实例,这是有问题的。

    直接调用构造函数显然是个坏主意(因为它将实体耦合到服务实现)。

    injecting services into entities is a bad idea .

    double dispatch '(有一些争论,如果这个名字是合适的)模式来解决这个问题。在这种方法中,域方法被调用方为域方法提供服务实现。在你的情况下,它看起来是这样的:

    class Foo {
      String bar    
    
      public boolean verify(Service emailService) {
        bar = "foo"
            if(this.save()) {
                emailService.sendConfirmation()
            }
      }
    }
    
    Foo.get(1).verify(new Service(...))
    

    最后(但并非最不重要)的选择是使用域事件模式。你可以在网上看到 Udi Dahan's blog . 在这种方法中,实体只负责发布由适当的处理程序订阅的有意义的事件。您可以阅读所有这些技术的完整比较 on my blog .

        2
  •  3
  •   Arnis Lapsa    16 年前

    这样做的坏处是您失去了域模型的隔离。 你的域模型知道电子邮件服务是纯粹的基础设施。

    事件模式也会起作用。

        3
  •  2
  •   cherouvim    16 年前

    我通常会从那个地方发确认信(行动?)将在何处调用from verify。如果验证的结果是发送许多确认邮件,那么我可能会 Foo 生成并返回 ConfirmationMessage

    话虽如此,如果你的 Service 是一个接口,您可以为测试注入mock,也可以为生产注入真实的mock,这样看起来就不错了。尽管我认为域对象最好持有关于自身的知识和逻辑,而不是关于另一层中的系统(服务)。