it-swarm.cn

全静态方法和应用单例模式之间有什么区别?

我正在建立一个数据库来存储有关我的网站用户的信息(我正在使用stuts2,因此Java EE技术)。对于数据库,我将建立一个DBManager。我应该应用单例吗?还是在这里使所有方法静态化?

我将使用此DBManager进行基本操作,例如添加,删除和更新用户配置文件。连同它,我将用于所有其他查询目的,例如,找出用户名是否已存在,并出于管理目的以及诸如此类的目的获取所有用户。

我的问题

  • 单例模式的好处是什么?
  • 这里最适合哪件事?所有静态方法还是单例模式?
  • 请比较两者。

附言数据库大于此。在这里,我仅讨论用于存储用户信息的表。

28
shahensha

为什么单例和静态方法是您唯一的选择?

从我的角度来看,这两种选择都非常糟糕。在 Singleton AntiPattern 上阅读。 Singleton模式的大多数用例是不正确的。

在您的情况下,我将使用实例对象并使用依赖项注入(如果使用的是DI框架)或 服务定位器/注册表模式

20
Tazzy531

使用单例类,您可以更好地控制如何管理所创建的对象。

首先,单例是一个对象。静态方法返回该对象的实例,并允许您仅创建一个实例,如果选择,则可以创建更多实例。

单例也被延迟加载,这意味着直到第一次调用它们时才实例化它们。

单例不使用静态方法,因此在非静态上下文中使用它不会有麻烦。

单例可以扩展/子类化。

由于它们是对象,因此可以将它们注入其他对象,从而可以利用依赖注入的概念创建一些出色的设计模式。例如,这就是Spring Bean IoC(控制依赖注入的反转)模型的工作方式。

15
jmort253

两者都不是理想的,但尤其不是一堆静力学。根据我的经验,这是一个真实的例子。我们谈到了一个数据库。每个人都说“只有一个”,所以有人使用了Spring配置的标准单例。然后添加了一个新要求:能够将我们的数据复制到另一个(远程)数据库中。哎呀。由于我们有一个代表数据库的实际对象,并且这是“很少使用的”功能,因此我可以通过创建临时副本并更改字段和值来对其进行破解,但是如果使用全局静态方法来实现,那将是一个真正的灾难。

以我的经验,当“他们”说将只有一个数据库,一个用户,一个应用程序,一个主窗口等时,“他们”是错误的。对于Singlton,您至少拥有重构和修复的机会。

3
user949300

全静态方法和应用单例模式之间有什么区别?

两者具有相同的效果:您可以调用类方法,而无需关心如何获取包含该方法的类的实例。

但是,如果要实现单元测试,则静态方法会遇到更多问题,因为它们不容易 模拟

从测试的角度来看,重新编写使用singeltons使其可与模拟进行单元测试的代码更加容易。

最灵活的解决方案是 Dependency_injection ,无论您使用的是di容器框架(如@ Tazzy531所建议的那样),还是要通过代码连接依赖项。

3
k3b

我希望这将回答这里的主要问题。

SO中已经很少有很好的答案了 。我只引用它们。

最佳答案- Heinzi

单例用于向应用程序引入某种全局状态。如果它是无状态的,那么我也看不到使用单例的意义,除非

  • 您希望在可预见的将来用状态来扩展它,或者
  • 您需要出于某种特定技术原因的对象实例(例如,对于C#SyncLock语句,尽管这已经牵强了)或
  • 您需要继承,即您希望能够使用相同的接口但使用不同的实现,轻松地用另一个替换单例。例如,Java中的Toolkit.getDefaultToolkit()方法将返回其确切类型与系统有关的单例。

高相关评论,通过 back2dos

(...)单身人士被滥用来引入全球状态。单例的目的不是使对象全局可用,而是强制对象仅实例化一次。全局对象是必不可少的邪恶。除非真正需要,否则应尽量不要使用它们,因为它们通常导致与SomeSingleton.getInstance()。someMethod()的高度耦合。

tzaman 也写了一个很好的答案:

我可以看到使用无状态单例而不是静态方法类的情况,即 Dependency Injection

如果您有直接使用的实用程序函数的帮助程序类,它将创建一个隐藏的依赖项;您无法控制谁可以在哪里使用它。通过无状态单例实例注入相同的帮助程序类,使您可以控制在何处以及如何使用它,并在需要时进行替换/模拟/等等。

使它成为单例实例仅可确保您不会分配任何不必要的类型的对象(因为您只需要一个)。

最后 (Sebastien )也很好地回答了自己:

实际上,我找到了这里未提及的另一个答案:静态方法更难测试。

看起来大多数测试框架都非常适合模拟实例方法,但是其中许多都不能以体面的方式处理静态方法的模拟。

话虽如此,我建议使用 工具箱模式

2
cregox