Singleton
版本: 1.0.1

本页内容
上下文
问题
影响因素
解决方案
示例
结果上下文
相关模式
致谢
上下文
在某些情况下,特定类型的数据需要提供给应用程序中的其他所有对象使用。在大多数情况下,这种类型的数据在系统中还是唯一的。例如,用户界面只能有一个所有应用程序必须访问的鼠标指针。同样,企业解决方案可能用单网关对象作为接口来管理与特定旧系统的连接。
问题
如何使对象实例全局可用,并保证仅创建一个此类的实例?
注意:相对 Design Patterns: Elements of Reusable Object-Oriented Software [Gamma95] 中的相关定义,此处特意缩小了 singleton 的定义。
影响因素
以下因素影响这种情况中的系统,在考虑上述问题的解决方案时必须协调这些影响因素:
-
很多编程语言(例如 Microsoft Visual Basic® 6.0 版或 C++)都支持全局对象的定义。这些对象位于命名空间的根部,应用程序中所有对象都可全局使用这些对象。此方法为全局可访问性问题提供了一个简单的解决方案,但是不能解决单实例要求。它无法禁止其他对象创建全局对象的其他实例。另外,其他面向对象的语言(例如 Visual Basic .NET 或 C#)不直接支持全局变量。
-
要确保某类仅有一个实例,则必须控制实例化过程。因此需要通过使用编程语言中的固有实例化机制(例如通过使用 new 运算符)来阻止其他对象创建该类的实例。控制实例化的另一方面是提供集中机制,所有对象都可通过该机制获得对此单个实例的引用。
解决方案
Singleton 通过下列方法提供唯一的全局实例:
-
让类创建自己的唯一实例。
-
允许其他对象通过可返回实例引用的类方法来访问此实例。类方法是全局可访问的。
-
将类构造函数声明为私有,从而任何其他对象都不能创建新实例。
图 1 显示了该模式的静态结构。UML 类图表非常简单,这是因为 Singleton 由一个简单类组成,而该类包含了对其自身的单个实例的引用。
图 1 显示,Singleton 类包含了公用类作用范围(静态)属性,该属性会返回对 Singleton 类的单个实例的引用。(UML 中的下划线表示类作用范围属性。)另外,右上角的数字 1 表示任何时候在系统中该类只能有一个实例。因为 Singleton 的默认构造函数是私有的,因此系统中的任何其他对象都必须通过 Instance 属性才能访问 Singleton 对象。
通常将 Singleton 模式归类为惯用语,而不是模式,这是因为该解决方案主要取决于所用编程语言的功能(例如类方法和静态初始值)。正如该模式集合所做的那样,将抽象的概念与特定的实现分隔开来可能会使 Singleton 实现看起来非常简单。
示例
有关示例请参阅在 C# 语言中实现 Singleton。
结果上下文
Singleton 会导致下列优缺点:
优点
-
实例控制 。 Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例。
-
灵活性。因为类控制了实例化过程,所以类可以灵活更改实例化过程。
缺点
-
开销。虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题,相关叙述请参阅"在 C# 中实现 Singleton"。
-
可能的开发混淆。使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
-
对象生存期。 Singleton 不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于 .NET Framework 的语言),只有 Singleton 类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致 Singleton 类中出现悬浮引用。
相关模式
有关详细信息,请参阅以下相关模式:
-
Abstract Factory [Gamma95]。在很多情况下,Abstract Factories 是作为 singleton 实现的。通常情况下,工厂应该能够被全局访问。将工厂限制到单个实例可确保一个工厂对创建对象进行全局控制。如果工厂从对象池中分配对象实例,则这样很有用处。
-
Monostate [Martin02]。Monostate 与 Singleton 相似,但它侧重于状态而不是身份。Monostate 不控制对象实例,而通过声明所有数据成员是静态的,从而确保所有实例仅存在一个共享状态。
-
使用服务器激活对象通过 .NET Remoting 实现 Broker。此模式使用 Singleton 工厂在服务器上创建新对象。
致谢
[Gamma95] Gamma, Helm, Johnson, and Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995.
[Martin02] Martin, Robert C. Agile Software Development: Principles, Patterns, and Practices. Prentice Hall, 2002.