关于c#:需要帮助避免使用Singleton

Need help avoiding the use of a Singleton

我并不讨厌单身汉,但我知道他们会被虐待,因此我想学会在不需要的时候避免使用他们。

我正在开发一个跨平台的应用程序(Windows XP/Vista/7、Windows Mobile 6.x、Windows CE5、Windows CE6)。作为过程的一部分,我将代码重新分解成单独的项目,以减少代码重复,从而有机会修复初始系统的错误。

应用程序中这样一个被分离的部分非常简单,它是一个配置文件管理器。此项目负责存储配置文件。它有一个Profile类,其中包含应用程序所有部分使用的一些配置数据。它有一个包含ProfilesProfileManager类。ProfileManager将读取/保存Profiles作为硬盘上的单独XML文件,并允许应用程序检索和设置"活动"Profile。简单。

在第一个内部构建中,图形用户界面是反模式智能图形用户界面。这是一个没有MVC/MVP的WinForms实现,因为我们希望它能更快地工作,而不是得到很好的设计。这导致ProfileManager成为一个单体。在应用程序的任何地方,GUI都可以访问活动的Profile

这意味着我可以根据需要访问ProfileManager.Instance.ActiveProfile来检索系统不同部分的配置。每个图形用户界面还可以对配置文件进行更改,因此每个图形用户界面都有一个保存按钮,因此它们都可以访问ProfileManager.Instance.SaveActiveProfile()方法。

我认为在这里使用单例并没有错,因为我认为它没有错,但我知道单例并不理想。有没有更好的办法来处理?是否应将ProfileManager实例传递给每个控制器/演示者?创建概要文件管理器时,是否应创建其他核心组件,并在概要文件更改时注册到事件。这个例子很简单,可能是许多系统中的一个常见特性,所以认为这是一个学习如何避免单例的好地方。

另外,我必须在CompactFramework3.5的基础上构建应用程序,它限制了许多可以使用的普通.NET框架类。


单例程序受到攻击的原因之一是,它们经常充当全局、共享(有时是可变)状态的容器。当应用程序确实需要访问全局共享状态时,单件是一个很好的抽象:例如,需要访问麦克风或音频播放的移动应用程序需要协调这一点,因为只有一组扬声器。

对于您的应用程序,您有一个单一的"活动"配置文件,应用程序的不同部分需要能够修改。我认为您需要决定用户的配置文件是否真正适合这个抽象。考虑到配置文件的表现形式是磁盘上的一个XML文件,我认为可以将其作为一个单独的文件。

不过,我认为您应该使用依赖注入或工厂模式来获取配置文件管理器。您只需要为需要使用概要文件来理解这一需求的类编写一个单元测试;您希望能够在运行时传递一个程序创建的概要文件,否则您的代码将与磁盘上某个XML文件有紧密耦合的依赖关系。


需要考虑的一件事是为您的profilemanager提供一个接口,并将该接口的一个实例传递给使用它的每个视图(或任何视图)的构造函数。通过这种方式,您可以很容易地拥有一个单例,或者每个线程/用户/etc拥有一个实例,或者拥有一个到数据库/Web服务/etc的实现。

另一种选择是让所有使用profilemanager的东西调用一个工厂,而不是直接访问它。然后,该工厂可以返回一个实例,也可以是一个单独的实例,或者不返回(转到数据库、文件或Web服务等),并且大多数代码不需要知道。

不回答你的直接问题,但它确实使未来变化的影响接近于零。


只有当"单例"基本上被用来替换"全局"变量时,"单例"才是最坏的。在这种情况下,如果这就是它的用途,它不一定是单件的。

在您描述的情况下,这是很好的,实际上是理想的,这样您的应用程序就可以确保概要文件管理器对所有需要它的人都可用,并且应用程序的任何其他部分都不能实例化与现有部分冲突的额外部分。这也减少了任何地方难看的额外参数/字段,您试图传递一个实例,然后维护对它的额外不必要的引用。只要它被强制为一个且只有一个实例,我就不会发现它有什么问题。

singleton的设计是为了避免多次实例化和单点"进入"。如果这就是你想要的,那就是你要走的路。只是要确保它有良好的记录。