【问题标题】:Inversion of control domain objects construction problem控制域对象构造问题的反转
【发布时间】:2010-12-23 22:42:35
【问题描述】:

据我了解,IoC 容器有助于创建应用程序级对象,例如服务和工厂。但是域级对象应该手动创建。 Spring 的手册告诉我们:“通常不会在容器中配置细粒度的域对象,因为创建/加载域对象通常是 DAO 和业务逻辑的责任。”

嗯。但是,如果我的域“细粒度”对象依赖于某个应用程序级对象怎么办。 例如,我有一个 UserViewer(User user, UserConstants constants) 类。 用户有域对象不能注入,但 UserViewer 还需要 UserConstants,这是 IoC-container 注入的高级对象。

我想从 IoC 容器中注入 UserConstants,但我还需要一个临时运行时参数 User。

设计有什么问题?

提前致谢!

更新

我的问题似乎不够准确。我真正需要的是一个如何做到这一点的例子:

创建类UserViewer(User user, UserService service)的实例,其中user作为参数传递,service从IoC注入.

如果我注入 UserViewer 查看器 那么我如何将 user 传递给它?

如果我手动创建 UserViewer 查看器,那么如何将 service 传递给它?

【问题讨论】:

    标签: dependency-injection inversion-of-control ioc-container


    【解决方案1】:

    这个设计没有错。您为此使用Factories,它在域中有一条腿,在基础设施中有一条腿。

    您可以手动编写它们,也可以让容器为您完成,例如温莎中的TypedFactoryFacility

    此外,当您的域对象来自持久层时,您可以将容器插入那里以注入他们需要的服务(NHibernate 可以做到这一点)。

    【讨论】:

      【解决方案2】:

      但是如果我的域“细粒度”对象依赖于某个应用程序级对象呢?

      正是这被认为是不好的做法。我想说的问题可能是:

      1. 此类对象数量众多,因此可能存在性能和内存问题。
      2. POJO 风格是可以在所有环境中使用(持久化在数据库中,在业务算法和规则中处理,在视图技术中读取和设置,序列化和通过网络发送)。在其中注入应用程序级对象可能会导致以下问题:

        1. 在您的体系结构中,您可能有这样的规则,即某些(大多数)应用程序级对象在某些层中可用,而在其他层中不可用。因为所有层都可以访问 pojo,所以会传递违反规则。
        2. 在另一个 JVM 中序列化和重建时,应用程序级对象的含义是什么。它们没用,必须将它们更改为本地等效项...

      通常,构成您的域的 pojo 是独立的。他们可以访问其他 pojo(和许多枚举),仅此而已。

      除了数据之外,它们还有实现业务规则或算法细节的方法记住 OO 的思想,即对数据和在其上工作的代码进行分组;-)):

      • 这在它们具有继承性时特别好,因为这允许通过提供不同的实现来为某些 pojo 自定义业务规则(没有 if 或 switch 的不同情况:还记得 OO 吗?;-)) .
      • 任何需要访问应用程序级对象(如访问数据库)的代码都会被删除,例如服务或管理器。但是该代码保持高级,因此可读且简单,因为 pojo 本身会处理低级细节(以及特殊情况)。

        事后,您经常会发现 pojo 方法被大量重用,并且由服务或管理器以不同的方式组合。这是减少重复的一大胜利,方法名称提供了急需的“含义”,并为刚接触模块的开发人员提供了更轻松的访问方式。

      【讨论】:

      • 好吧。但是什么是 UserViewer?它是域还是应用程序对象?它不是 POJO,但似乎不是真正的应用服务。它既需要访问应用程序对象,也需要访问 POJO 对象。我如何实例化它?还是我应该只将 POJO 作为参数传递?这通常很不方便。
      • @Andrey 1. 任何代码都可以使用 pojo,应用程序对象也不例外。 2. 举例来说,我给出了不同的答案。
      • KLE!起初我没有明白你的意思,但现在我开始明白了。谢谢!我还有一个问题:这个 POJO + Services 模型很好,但它不是太程序化和反 OOP 吗?
      • @Andrey 不客气 :-) 关于您的“程序”问题,我理解您的担忧。然而,事实并非如此。评论区太小了,无法分析为什么会这样......但是你已经在我的回答中有一些解释...... ;-)
      【解决方案3】:

      为了您的更新:

      创建类UserViewer(User user, UserService service)的实例,其中user作为参数传递,服务从IoC注入。

      如果我注入 UserViewer 查看器,那么如何将用户传递给它?

      如果我手动创建 UserViewer 查看器,那么如何将服务传递给它?

      在这种情况下,您需要一个工厂方法(可能在您的工厂或定位器上)。它可以看如下,将两部分分开:

      public UserViewer createUserViewer(User user) {
         UserViewer viewer = instantiateBean(UserViewer.class); 
         viewer.setUser(user);
         return viewer;
      }
      
      private <E> E instantiateBean(Class<E> clazz) {
         // call the IoC container to create and inject a bean
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-16
        • 1970-01-01
        相关资源
        最近更新 更多