您的位置:首页 > 编程语言 > C#

单例模式以及在C#中的使用

2013-06-18 11:51 99 查看
下面做一些简要的说明。

1.

单例模式(Singleton Pattern),又称作单件模式,当然也有一种诙谐的称谓:单身模式。在经典的GoF所著的《Design Patterns》一书中,对单例模式有着详尽的介绍,这本书网上有全文版本

2.

单例模式的意图是保证一个类仅有一个实例,并且要提供一个全局访问点来访问这个实例。通常这个全局访问点是一个静态方法或者C#中的一个属性。

3.

在C#中,典型的单例模式实现方法可以如下:

当外部需要
Manager
的实例时,可以调用
GetInstance()
这个静态方法。由于
Manager
类的构造器是私有的,这也就避免了其他方式实例化这个
Manager
类。
GetInstance()
方法内部的实现,保证了全局中只有一个
Manager
实例。

4.

问题肯定不会这么简单就被解决,比如在多线程环境中,上述代码就会有很大的隐患。

有一种情况很常见:两个线程同时调用
GetInstance()
方法;

当某一个线程由于
Mgr
null
而进入条件判断代码块的时候,而恰恰还没有执行实例化一个
Manager
对象,这时候另一个线程由于
Mgr
null
,所以也会进入这个条件语句中

上面两种情况,很显然都会创建
Manager
实例,这也就违背了单例模式的意图了。

利用C#的特性,我们可以把一个线程先锁住(
lock
),等到这个线程完成后,再让下一个线程访问
GetInstance()
方法:

代码中用到了双重检查锁定(double check locking)的技术,是为了提高性能考虑,因为C#中
lock
语句是很耗性能的。第一道检查,是基于如果
Mgr
不为
null
的时候就不需要
lock
了,提高性能。第二道检查,是基于两个线程同时通过第一道检查后,第一个线程解锁后,由于
Mgr
此时已经不为
null
,所以第二个线程就不用实例化
Manager
了。

5.

单例模式有两种实现方式,主要基于构建的方式不同:

延迟初始化(Lazy Initialization),也叫“懒汉模式”:单例实例在第一次使用时被构建;

热初始化(Eager Initialization),也叫“恶汉模式”:单例实例在类加载时创建

前面创建单例模式的方式都属于延迟初始化。.NET 4.0以后提供了一个
Lazy<T>
泛型类,可以被应用于这个场景,省却代码的编写量。

Lazy<T>
构造器重载版本可以帮我们解决多线程的问题。

C#使用静态初始化来完成单例模式中的热初始化。需要注意的是,不需要考虑多线程的问题,因为CLR会自动解决多线程同步的问题。如果程序经常要用到这个实例,运用热初始化可以显著提高性能。

6.

StackOverflow中对于单例模式都是持否定态度的,比如这个


In theory: when you need to restrict the instantiation of an object to one instance. In practice: never.


主要基于下面几个原因:

违反了单一职责原则

耦合度过大

单元测试基本无法进行

开发混淆,造成混乱。比如作为API提供的时候。

总之,


There‘s at most a can use but there no need.


文章来源:http://laobian.me/2013/02/singleton-pattern-with-csharp.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: