【问题标题】:How to maintain a centralized Object across the application如何在整个应用程序中维护一个集中的对象
【发布时间】:2013-07-26 14:19:12
【问题描述】:

我正在开发一个应用程序,我需要创建一个对象并且多个类必须访问和修改该对象。如何查看其他类对象最近所做的更改以及如何通过所有类集中访问该对象而不将该对象作为参数传递给所有类?

我正在创建一个 Apache POI 文档,我将在其中添加多个表格、多个页眉/页脚和段落。我希望我的应用程序中只有一个 XWPFDocument 对象。

有什么设计模式可以实现吗?

【问题讨论】:

  • 你在寻找一个全局对象吗,这很糟糕!
  • 那么最好的方法是什么?建议我@TheNewIdiot
  • @TheNewIdiot 拥有一个全局对象还不错,因为您可能只需要通过应用程序的单个实例,问题是您打算如何维护这个单个实例。
  • @LuiggiMendoza 谢谢你理解要求
  • 根据您对实际问题的描述,看起来您在创建文档时需要一个 XWPFDocument 实例。这可以通过构建器设计模式来完成。

标签: java design-patterns


【解决方案1】:

singleton design pattern工作 - 但不是很干净;您最终会得到难以跟踪和测试的全局静态状态。如今,它通常被认为是一种反模式。在非常少数情况下它仍然有意义,但我尽量避免它。

更好的方法是使用dependency injection:让每个需要这些对象之一的类声明该类型的构造函数参数(或者可能具有可设置的属性)。每个类都不应该太关心对象的共享方式或其他方式(除了意识到它可以共享)。然后由初始化应用程序的代码来决定应该共享哪些对象。

有多种可用于 Java 的依赖注入框架,包括 GuiceSpring。这些框架的想法是在适当的配置下自动连接应用程序中的所有依赖项。

【讨论】:

  • +1,但有状态的单例 -> 不! ,如果它是一个单节点 webapp,我会将它存储在 servlet 上下文中
  • @JigarJoshi:当我写答案时,OP 没有包含该上下文。我会适当地编辑。 (我不确定我是否会使用 servlet 上下文......)
  • @JonSkeet 只有一个 XWPFDocument 实例应该出现在整个应用程序中。这样我就可以在另一个类中附加文本。例如,在一个类中,我在文档中添加了一个 tableA,而在其他类中,如果我添加了必须使用现有文档实例的 tableB,它添加了 tableB,它在文档中的 tableA 之后。
  • @MaheshVarma:是的,因此您为两个类的构造函数提供了对同一文档的引用。
  • 这里有一个很好的依赖注入教程lowcoupling.com/post/47844360084/…。主要思想是,为了避免单例,您使用单例(或具有静态方法的类)来注入对象:))
【解决方案2】:

为此有Singleton Pattern,它为应用程序创建一个实例,并且无需传递即可共享。

但这不是最好的选择。

为什么这是一个糟糕的选择?

  • 不利于代码的可测试性
  • 设计上不可扩展

比单例模式更好的是应用程序范围的单实例

为应用程序创建一个对象并使用一些上下文对象共享它。 Misko in his guide to testable code

对此进行了详细解释

单实例而非单例模式

它代表应用程序范围的单个实例,它通过静态实例字段强制其单例。

为什么单例很难测试?

  • 静态访问防止与另一个类的子类或包装版本协作。通过硬编码依赖关系,我们失去了多态性的力量和灵活性。 - 每个使用全局状态的测试都需要它以预期的状态开始,否则测试将失败。但另一个对象可能在之前的测试中改变了该全局状态。
  • 全局状态通常会阻止测试能够并行运行,从而迫使测试套件运行得更慢。
  • 如果您添加一个新测试(它不会清理全局状态)并且它在套件中间运行,那么在它之后运行的另一个测试可能会失败。
  • 单身人士执行他们自己的“单身人士”最终会作弊。 您经常会在所谓的单例上看到诸如reset()setForTest(…) 之类的mutator 方法,因为您需要在测试期间更改实例。如果您在测试后忘记重置 Singleton,以后的使用将使用陈旧的底层实例,并且可能会以难以调试的方式失败。

【讨论】:

  • 我从未听说过“带有小 s 的单例”——创建一个对象的单个实例与将其设为单例不同。单例防止多个实例被创建。这个术语只会导致混乱,IMO。
  • @JonSkeet 我在 Misko 的博客中读过它,我的答案中有链接。与单例模式相比,IMO 是一个更好的选择。我也会在答案中添加含义。
  • 您提到的文章明确指出“添加或使用单例”是一个警告标志 - 所以它甚至在在同一页面内不一致。当然,这表明这种微妙的差异值得避免。
  • @JonSkeet 我同意,但我对这篇文章持肯定态度,为了可测试性,我避免使用 Singleton。
  • 如果您同意避免使用术语,您为什么要在帖子中宣传它?为什么不只谈论在应用程序启动时创建的单个实例,而不是尝试将其称为“带有小 s 的单例”?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 2019-06-13
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
相关资源
最近更新 更多