【问题标题】:How to package Factories in Java如何在 Java 中打包工厂
【发布时间】:2010-12-26 00:45:28
【问题描述】:

我想知道如何打包我在应用程序中拥有的工厂。 Factory 应该与使用它的类在同一个包中、与其创建的对象在同一个包中还是在它自己的包中?

感谢您的宝贵时间和反馈

【问题讨论】:

    标签: java design-patterns factory packaging


    【解决方案1】:

    通常工厂和它们创建的对象在同一个包中;毕竟他们的目的是创建这些对象。通常它们不在单独的包中(没有理由这样做)。此外,将工厂与它们创建的对象放在同一个包中,这样您就可以利用包的可见性。

    【讨论】:

    • 详细地说,通过exploit package visibility,我认为你的意思是工厂创建的实例的具体类型可以是包范围的——不公开可见——然后工厂是创建符合某个接口的类型的唯一公共手段。通过将工厂创建的类型定义为具有 package-private 构造函数的抽象类,可以实现更严格的锁定;子类只能在包含的包中定义。 java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html
    • 我同意。在我看来,将工厂放在专用的“工厂包”中甚至是错误的,因为包组织应该由领域概念驱动(我是 DDD 的粉丝 :-))。
    【解决方案2】:

    Factory 的全部意义在于拥有一种可配置 方式来为接口创建实现实例。将工厂与其提供的实现类放在同一个包中的约定增加了一个完全您将来不太可能遇到的不必要的限制。此外,如果返回的实现在所有上下文中都不相同,将它放在同一个包中就更没有意义了。

    例如,想象一个在应用程序的客户端和服务器部分之间共享的服务查找工厂,它返回客户端上的客户端实现(位于仅客户端包中) ,以及从服务器运行时调用时的服务器端实现(在仅服务器包中)。

    您的工厂甚至可以是可配置的(我们通过一个 XML 文件来实现这一点,该文件定义为哪个接口返回哪个实现类),因此可以轻松切换实现类,或者可以为不同的上下文使用不同的映射。 例如,在进行单元测试时,我们使用返回接口的模型实现的配置(确实能够进行不是集成测试单元测试),它会使要求这些模型实现与工厂在同一个包中完全没有意义,因为它们是测试代码的一部分,而不是运行时代码。

    我的建议:

    • 不要添加任何包限制 实现类,就像你一样 不知道有哪些实现 在未来使用,或在不同的 上下文。
    • 接口可能在同一个 包,但这个限制也是 不必要的,只会使 配置僵化。
    • 可配置工厂(例如服务查找)可以重复使用和 跨项目共享时 接口/实现映射 不是硬编码的。仅这一点 有理由拥有工厂 与两个接口分开 和实现类。

    【讨论】:

    • 我同意你的观点,但这并不意味着你必须在实现类以外的地方打包工厂。可能存在所有实现类都在同一个包中的情况,并且永远都是。我认为这两种情况都是合理的。取决于应用程序。
    • 是的,很多时候实现类在项目的整个生命周期中都保持不变,通常工厂中每个接口都有一个实现类。但是,工厂的重点是保持开放并允许将来交换实现类。向工厂添加包限制将违反其意图并阻碍将来的重构(通过交换实现)。即使对于您非常确定永远不会交换实现类的项目,最好保持这一点开放。
    【解决方案3】:

    unit of reuse is the unit of release。这意味着不应该存在跨包的耦合,因为包通常是最低粒度的发布。当你组织一个包时,想象你自己说,“这里有你使用这些类所需要的一切。”

    【讨论】:

      【解决方案4】:

      这完全取决于您打算使用上述工厂的方式。有时将工厂放在自己的包中是有意义的。

      例如,您可能有一个接口foo.bar.ui.Interface。您希望对该接口有不同的实现,一种用于 AWT,一种用于 Swing,一种用于控制台,等等。然后创建一个 foo.bar.ui.swing.SwingInterfaceFactory 来创建一个 foo.bar.ui.swing.SwingInterface 会更合适。然后foo.bar.ui.awt.AWTInterface 的工厂将驻留在foo.bar.ui.awt.AWTInterfaceFactory

      重点是,没有永远遵循这条规则。使用适合您的问题的任何方法。

      【讨论】:

      • 这里不能同意。我看不出跨包依赖是一个好主意。也看不到创建具有一个类的包的用途。另一件事 - 这样一个工厂的目的不是向调用者隐藏 Swing 和 AWT 吗?我认为您将拥有一个工厂和 foo.bar.ui.Interface 的具体 AWT 和 Swing 实现。此外,“发布/重用”实际上是普遍接受的“始终遵循”原则。我敢肯定有人会想到一个例外(我不能随便),但就一般原则而言,这个是相当可靠的。
      【解决方案5】:

      我喜欢将工厂放在为其创建对象的包中,命名是这里的关键,如果命名清晰透明,它将有助于维护工作。

      例如,动作工厂可以构造为:

      • org.program.actions
      • 接口org.program.actions.Action
      • 枚举org.program.actions.ActionTypes
      • 工厂org.program.actions.ActionFactory(或.ActionManager
      • 动作实现类org.program.actions.LogAction

      在整个项目中遵循这样的模式有助于项目成员在他们以前没有参与过的项目中找到他们实际所在的类。

      【讨论】:

        【解决方案6】:

        为什么不呢。如果没有其他反对意见,请尽可能接近。其实为什么不呢

        public interface Toy
        {
            static class Factory
            {
                public static final Toy make() { ... }
            }
        }
        
        Toy toy = Toy.Factory.make();
        

        哈!

        但是 make() 不应该静态地依赖于 Toy 的子类,那会很糟糕。它可以做一些动态的魔法,取决于你的工厂策略。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-10
          • 2013-10-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多