java - 单例适合这种设计吗?

标签 java design-patterns singleton

我的模型已实现,我正在处理 View 。

我有一个名为 Helper 的类,它是我的 Controller 的一部分。 Helper 类的目的是包含模型的“主副本”。其他类将调用 Helper 方法来请求它们自己的模型副本(整个或特定部分)。 Helper 也是唯一应该允许对模型进行更改的类。

我正在处理的 View 包含一个名为 DrawingPanel 的 JPanel。 DrawingPanel 的 Paint() 方法被重写,以便它在绘制自身之前从 Helper 检索模型。

将 Helper 类实现为单例是实现此目标的最佳方法,还是有更好/更简单/更优雅的方法来实现我的目标?

我想我还应该提前知道我作为单例实现的 Helper 是否需要线程安全。该 GUI 是用 Swing 设计的。

最佳答案

至于大写的“Singleton”是否合适......问问你自己......

Is a second instance certain to cause the death of my program?

(我的意思是“确定”和“死亡”。不仅仅是“可能”......而且不仅仅是对哪个实例是“官方”实例的一些困惑。如果程序崩溃、内爆、打开虫洞,放火烧你的狗等完全是由于第二个实例的存在,答案是"is"。如果您不确定,请假设“否”,直到您有确凿的证据为止。)

如果答案是"is",那么您可能有使用 Singleton 的有效案例。如果没有,那么你就滥用了它,并且有一个更好的解决方案: 只是不要创建第二个实例。

使用 Singleton 有几个被误导的原因:

  • “我希望能够使用我的对象,而无需在应用程序中传递它。”你猜怎么了?你拥有的是一个美化的全局变量。当它隐藏在某个类(Class)的内心深处时,它比它公开展示给全世界时更加邪恶。 如果你想使用全局变量,那就使用一个奇怪的全局变量。不要把它隐藏在 getter 后面,以为人们不会注意到。

  • “我只需要其中一个。”往上看。 你只需要一个?只创建一个。无论您现在是否需要它,您是否有充分的理由强制只有一个?如果将来你想要另一个怎么办?您不仅让创建另一个类变得很痛苦,而且您可能以一种只能存在一个类的方式构建您的类,并且将有很多“设计”需要撤销。

  • “能够说出 MySingleton.getInstance() 很方便。”是的,直到你开始关心测试。您看,每次调用 MySingleton.getInstance() 时,您都添加了一个假设:这是该对象的唯一类型。如果您开始搞乱单元测试,那么您的测试将几乎毫无用处,因为它们都取决于该实例的行为,甚至取决于测试运行的顺序。即使是全局变量对于可测试性来说也没有那么糟糕,而且有点糟糕。 (另请参阅上面的“...而不将其传递到应用程序各处”。)

单例问题的解决方案一般是依赖注入(inject)。话虽大,但前提非常非常简单;非框架版本基本上是“对象完成其工作所需的外部东西?将其传递给构造函数。”据称,有一些 DI 容器库/包可以简化这一过程,但这一切都只是告诉对象要使用什么,而不是让它自己去寻找东西。因此,您将一个实例传递给需要它的对象,并且它永远不必说MySingleton.任何内容 - 甚至关心是否是这样对象是否是单例。

关于java - 单例适合这种设计吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11908982/

相关文章:

ruby-on-rails - 如何在 Rails 3.2.12 中为实例的方法定义只读单例方法?

java - Java 中的 JAXB 字符串到 JPA 日期

python - 设计启发式方法来编写与 `scipy.integrate.odeint` 交互的 Python 类?

.net - 如何实现单例 .NET 组件以供多个进程使用?

java - Swing/SwingWorker 初学者的问题

java - 在 View 中保留 Controller 的引用或使用监听器

java - 具有昂贵成员实例的 Guice Provider 是否应该使用 @Singleton 进行注释?

c# - 如何在文件上的 C# 和 Java 之间读取/写入无符号字节数组?

java - Mockito - 模拟相同类型的通用对象

java - fragment 刷新?