Singleton Design Pattern
The Singleton pattern is one of the simplest design patterns, which restricts the instantiation of a class to ONLY ONE object. A singleton class only allows a single instance of itself to be created, and usually gives simple access to that instance. Most commonly, singletons don't allow any parameters to be specified when creating the instance.
In this article, we would provide different ways of implementing the singleton pattern using C# and discuss the difference in terms of lazily-load, thread-safety, and perfromance.
Singleton and Static Class
Before describing the implementations, we clarify the difference between singletons and static classes. We can make a global single class by using keyword static. Both singleton and static class have only one instance of them. The static classes are usually used for storing global data, all the data in a static class are also static. A singleton is treated as a normal class (without static keyword) with state, which allows you to reuse code and control object state much easier. We can extend classes or implement interfaces with singletons but not with static classes. Aslo, a singleton is allocated in heap and a static class is allocated in stack.
Instantiation: Lazy vs Eager
// Implementation 1: lazy instantiation, not thread-safe! Do not use!
public class Singleton1
{
private static Singleton1 mInstance = null; // Private constructor
private Singleton1() { } // GetInstance
public static Singleton1 Instance
{
get
{
if (mInstance==null)
{
mInstance = new Singleton1();
}
return mInstance;
}
}
} // Implementation 2: eager instantiation, simple thread-safe without using locks
public sealed class Singleton2
{
private static readonly Singleton2 mInstance = new Singleton2(); // Private constructor
private Singleton2() { } // GetInstance
public static Singleton2 Instance
{
get
{
return mInstance;
}
}
}
The Singleton1 implementation is bad because it is not thread-safe. Two different threads could both pass the if test when the mInstance is null, then both of them create instances, which violates the singleton pattern. The advantage of this implementation is the instance is created inside the Instance property method, the class can exercise additional functionality. The instantiation is not performed until an object asks for an instance, so called "Lazy Instantiation", the lazy instantiation avoids instantiating unnecessary singletons when the application starts.
The Singleton2 implementation is an eager initialization, which will always create an instance. In this implementation, the instance is created the first time any member of the class is referenced, the common language runtime takes care of the variable initialization. The class is marked sealed to prevent derivation, which could add instances. The instance variable is marked readonly which means that it can be assigned only during static initialization or in a class constructor. Hence, the *private* constructor ensures that the instance variable can be instantiated only inside the the class and therefore only one instance can exist in the system. The downside of this implementation is that you have less control over the mechanics of the instantiation.
Thread-safety
// Implementation 3: thread-safe with locking the shared object
public sealed class Singleton3
{
private static Singleton3 mInstance = null;
private static readonly object SingletonLock = new object(); Singleton3() { } public static Singleton3 Instance
{
get
{
lock (SingletonLock)
{
if (mInstance == null)
{
mInstance = new Singleton();
}
return mInstance;
}
}
}
}
In the Singleton3 implementation, all threads share a lock object to ensure that only one thread will create an instance, because only the first thread entering in the critical section can find the instance variable is null and pass the if check. The withdraw of this implementation is obvious, the performance suffers as a lock is acquired every time the instance is requested.
The Singleton4 implementation improve the performance by avoiding the unnecessary lock operator. To do so, it uses a double null-check to avoid taking out a lock every time. However, this implementation doesn't work in Java and is easy to get wrong.
// Implementation 4: double null-check. Bad code! Do not use!
public sealed class Singleton4
{
private static Singleton4 mInstance = null;
private static readonly object SingletonLock = new object(); Singleton()
{
} public static Singleton4 Instance
{
get
{
if (mInstance == null)
{
lock (SingletonLock)
{
if (mInstance == null)
{
mInstance = new Singleton4();
}
}
}
return mInstance;
}
}
}
Laziness and Performance
To be fully lazy instantiated, Singleton5 implementation uses a nested class in the singleton class. Therefore, the instantiation is triggered the first time the nested class is referenced which could only occur in Instance. This implementation is fully lazy and has better performance than previous implementations.
// Implementation5: fully lazy using nested class
public sealed class Singleton5
{
private Singleton() { } public static Singleton5 Instance
{
get
{
return Nested.instance;
}
} private class Nested
{
static Nested()
{
}
// Make the instantiation
internal static readonly Singleton instance = new Singleton5();
}
}
If you're using .NET 4 or higher, you can use the System.Lazy<T> type to make the laziness really simple. As shown in Singleton6 implementation, all you need to do is pass a delegate to the constructor which calls the Singleton constructor - which is done most easily with a lambda expression. It's simple and performs well. Aslo, you can check whether the instance has been created with the IsValueCreated property.
// Implementation6: fully lazy, .NET 4 or higher only
public sealed class Singleton6
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton6()); private Singleton() { } public static Singleton Instance
{
get
{
return lazy.Value;
}
}
}
References:
http://csharpindepth.com/articles/general/singleton.aspx
http://msdn.microsoft.com/en-us/library/ff650316.aspx
Singleton Design Pattern的更多相关文章
- python singleton design pattern super() 多继承
python singleton design pattern decorate baseclass metaclass import module super() 一.A decorator de ...
- Design Principle vs Design Pattern 设计原则 vs 设计模式
Design Principle vs Design Pattern设计原则 vs 设计模式 来源:https://www.tutorialsteacher.com/articles/differen ...
- Design Pattern —— Singleton
Design Pattern —— Singleton 强力推荐枚举和类级内部类方式实现单例模式 单例模式是开发中非常常用的一种模式,简单的说,我们希望一个类永远都只有一个对象. 主要有两个用途: ...
- [Design Pattern] Singleton Pattern 简单案例
Singleton Pattern, 即单例模式,用于获取类的一个对象,该对象在整个应用中是其类的唯一对象.单例模式属于创建类的设计模式. SingleObject 作为单例类,内含了一个静态私有的 ...
- 说说设计模式~大话目录(Design Pattern)
回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...
- 设计模式(Design Pattern)系列之.NET专题
最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...
- [转]Design Pattern Interview Questions - Part 4
Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...
- [转]Design Pattern Interview Questions - Part 1
Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...
- Null Object Design Pattern (Python recipe)
Null Object 个人感觉非常有用.也是在review公司其他同事写代码的时候看到. 当时使用了flask的request全局请求变量g,然后使用了g.x保存了一个东西. 当时在view代码读取 ...
随机推荐
- 编辑美化图片,保存至本地,Adobe出品(支持IOS,android,web调用)免费插件
本例以web调用做为例子,本插件支持主流浏览器,IE要9以上,移动设备,触屏设备也支持,能自适应屏幕大小. 使用效果: 工具还是很丰富的,编辑完成之后,可以保存图片至本地目录. 使用说明: 1,需要在 ...
- c# applibrary实现一个Sheet表中存放多张DataTable数据
1.工具类(applibrary.dll) public class ExcelHelper { /// <summary> /// 文件名 /// </summary> pu ...
- innoDB 存储引擎
innodb 是在mysql 5.5.8 及之后的版本中成为mysql的默认存储引擎.之前都使用myisam. innodb 是事务型的存储引擎 支持ACID事务,适用于小事务. 1.表空间类 ...
- Eclipse+Maven创建webapp项目
Eclipse+Maven创建webapp项目<一> 1.开启eclipse,右键new-->other,如下图找到maven project 2.选择maven project,显 ...
- CAS实现SSO单点登录原理
1. CAS 简介 1.1. What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨 ...
- MRPT笔记——使用编译好的MRPT库建立VS2013项目
接着上一篇<MRPT在VS2013中的配置>,下面接收如何使用编译好的MRPT建立工程项目. 一.设置环境变量 上一篇中,配置MRPT时,使用到了几个相关库,opencv.zlib.wxW ...
- 在eclipse的maven插件中搜寻本地仓库中的jar搜索不到的解决方案
在eclipse的maven插件中搜寻本地仓库中的jar搜索不到的解决方案 之前,用过maven管理项目的童鞋都知道本地会有一个${User_Home}.m2/repository仓库 是用来存放ja ...
- mysql5.7.10免安装版出现的问题及应对
在对应目录下新建my.ini [mysqld] # 设置mysql的安装目录 basedir=D:\mysql-5.7.10 # 设置mysql数据库的数据的存放目录,必须是data datadir= ...
- 字符编码和python .encode().decode()方法
字符编码与encode.decode的问题: 用8个开关表示世界万物 ASCII : American Standard Code for Information Interchange,美国 ...
- 例子:Bluetooth app to device sample
本例子演示了: 判断蓝牙是否打开,是通过一个HRsult值为0x8007048F的异常来判断的 catch (Exception ex) { if ((uint)ex.HResult == 0x800 ...