如何重构单例class,避免重蹈覆辙

How to refactor a singleton class and avoid doing the same mistakes again

我在 WPF 中启动了一个小应用程序并使用单例 class 来处理所有应用程序逻辑。另外,我有一些 ObservableCollections 绑定到视图上的 DataGrids。

问题:本来应该是一个小程序的功能开始增加,代码现在太难维护、重用并且代码耦合度很高。

因此我开始将代码移至其他 classes。例如,我有一个只处理文件读数的 class。我已将此 class 设为静态,因为我只 运行 这些方法一次(当我需要将数据导入数据库时​​),当它们完成后,我不再需要这些对象,只是忘记了他们存在。

现在我正在考虑对其他方法做同样的事情,比如从数据库中检索数据的方法。

我怀疑这是否是解决问题的正确方法?恐怕使用静态 classes 会像单例的乘法。

静态 classes 被一些人认为是邪恶的,但这只是一种观点。当我有这些问题时,我看一下.NET-framework:里面是怎么解决的?

有时可以将单例重构为静态 class。这取决于实际情况。如果你的单例是继承(阅读:必须继承)其他classes或接口的类型,它不能转换为静态class,因为静态class不能继承任何东西。

如果创建静态class,尽量遵守以下规则:(.NET框架也遵守这些规则):

  • 所有静态成员必须是线程安全的。

就是这样! :)

这条规则听起来很简单,但蕴含着很多:

  • 所有静态成员彼此独立工作。所以一个调用永远不会影响另一个调用的结果。
  • 不允许静态 class 保持(静态)状态。
  • 如果 class 有静态字段,请确保它们是只读的或常量的。确保这些字段的内容永远不会改变。

当然也有一些小例外。例如:静态 class 可以维护一个用于缓存结果的内部字典。修改这个缓存必须是线程安全的。因为它是内部的东西,所以对于外部世界,静态 class 仍然遵守上述规则。

所以...简而言之:如果您的单例不是线程安全的(保持状态等),请不要将其转换为静态 class。

* 编辑 *

使用单例通常意味着您有一个静态 属性 包含一个特定类型的实例。由于这是一个静态 属性 它也必须遵守上述规则,这意味着该实例必须是线程安全的。

如果您的(单例)实例不是线程安全的,请重新设计您的应用程序,使其不使用此单例或静态 class。让所有代码在需要时创建此 class 的新实例。