17

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

感谢您的时间和反馈

4

6 回答 6

26

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

于 2009-12-12T17:29:02.060 回答
6

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

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

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

我的建议:

  • 不要在实现类上添加任何包限制,因为您不知道将来会使用哪些实现,或者在不同的上下文中使用。
  • 接口可能在同一个包中,但这种限制也是不必要的,只会使配置变得僵硬。
  • 当接口/实现映射没有硬编码时,可配置工厂(例如服务查找)可以在项目之间重用和共享。仅这一点就证明了将工厂与接口和实现类分开是合理的。
于 2009-12-14T09:36:36.030 回答
3

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

于 2009-12-12T19:14:33.877 回答
0

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

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

  • 包裹org.program.actions
  • 界面org.program.actions.Action
  • 枚举org.program.actions.ActionTypes
  • 工厂org.program.actions.ActionFactory(或.ActionManager
  • 动作实现类org.program.actions.LogAction

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

于 2009-12-12T17:57:51.717 回答
0

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

例如,您可能有一个接口,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.

关键是,没有永远遵循这条规则。使用适合您的问题的任何东西。

于 2009-12-12T18:50:33.067 回答
0

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

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

Toy toy = Toy.Factory.make();

哈!

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

于 2009-12-13T00:36:39.797 回答