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的更多相关文章

  1. python singleton design pattern super() 多继承

    python  singleton design pattern decorate baseclass metaclass import module super() 一.A decorator de ...

  2. Design Principle vs Design Pattern 设计原则 vs 设计模式

    Design Principle vs Design Pattern设计原则 vs 设计模式 来源:https://www.tutorialsteacher.com/articles/differen ...

  3. Design Pattern —— Singleton

    Design Pattern —— Singleton   强力推荐枚举和类级内部类方式实现单例模式 单例模式是开发中非常常用的一种模式,简单的说,我们希望一个类永远都只有一个对象. 主要有两个用途: ...

  4. [Design Pattern] Singleton Pattern 简单案例

    Singleton Pattern, 即单例模式,用于获取类的一个对象,该对象在整个应用中是其类的唯一对象.单例模式属于创建类的设计模式. SingleObject 作为单例类,内含了一个静态私有的 ...

  5. 说说设计模式~大话目录(Design Pattern)

    回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...

  6. 设计模式(Design Pattern)系列之.NET专题

    最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...

  7. [转]Design Pattern Interview Questions - Part 4

    Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...

  8. [转]Design Pattern Interview Questions - Part 1

    Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...

  9. Null Object Design Pattern (Python recipe)

    Null Object 个人感觉非常有用.也是在review公司其他同事写代码的时候看到. 当时使用了flask的request全局请求变量g,然后使用了g.x保存了一个东西. 当时在view代码读取 ...

随机推荐

  1. 14071702(SkeletalControl_Limb)

    [目标] SkeletalControl_Limb [思路] HumanIK的15 个节点 CCDIK [步骤] 1 先编译[!BuildAll] [注]先把SYSTEM文件夹该为非只读属性,编译生成 ...

  2. CentOS6.5 下安装 texlive2015 并设置 ctex 中文套装

    0 卸载旧版本的 texlive 0.1 卸载 texlive2007 如果系统没有安装过texlive,则跳过第0步. 可以在终端中使用如下命令查询本机已经安装的tex和latex版本: [She@ ...

  3. pwnable.kr-random

    题目 首先我们要对rand&srand有个总体的看法:srand初始化随机种子,rand产生随机数,下面将详细说明. rand(产生随机数) 表头文件: #include 定义函数 :int ...

  4. iOS开发_数据存储方式

    对于数据持久化的问题,博主并不准备在博文内放很多的代码进行更深一步解释,只是简单的介绍一下四种数据持久化,如有时间,会另外针对各个数据持久化的方法进行更进一步的阐述. 直接进入主题: 〈1.NSUse ...

  5. 4种必须知道的Android屏幕自适应解决方案

    文章来源:http://blog.csdn.net/shimiso/article/details/19166167 demo下载:http://www.eoeandroid.com/forum.ph ...

  6. 带领大家安装Rational rose

    Rational rose下载地址:http://pan.baidu.com/s/1hqIIyJq?qq-pf-to=pcqq.c2c 下载好后,文件里有4个安装文档: 解压CD1和CD2到当前目录, ...

  7. ObReferenceObjectByName函数调用WIN7下的解决

    <寒江独钓 Windows内核安全编程>第4章键盘的过滤ctrl2cap代码中,ObReferenceObjectByName函数调用: [1]extern POBJECT_TYPE Io ...

  8. Visual Basic 2012 借助DataGridView控件将SQL server2012 数据导入到Excel 2010

    摘  要: SQL Server 2012 数据和Excel 2010之间的连接和数据的传输,本篇文章主要针对的是SQL Server 2012 数据导入到Excel 2010文件中.Excel软件对 ...

  9. Scipy学习笔记 矩阵计算

    Scipy学习笔记 非本人原创  原链接 http://blog.sina.com.cn/s/blog_70586e000100moen.html 1.逆矩阵的求解 >>>impor ...

  10. 【墙内备份】Android 6.0 APIs

    Android 6.0 APIs In this documentSHOW MORE Fingerprint Authentication Confirm Credential App Linking ...