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. 如何在MySql中记录SQL日志记录

    My SQL可以用下面方法跟踪sql 语句,以下方法以Windows平台为例,linux雷同:   1  配置my.ini文件(在安装目录,linux下文件名为my.cnf     查找到[mysql ...

  2. 多行溢出隐藏显示省略号功能的JS实现

    在页面重构中,经常需要将过多的内容隐藏而显示部分.在单行文本中实现非常简单,但是在多行文本中,则需要根据实际选择不同的方式. 用CSS实现多行溢出隐藏的代码非常简单,但是兼容性也相对较低. displ ...

  3. DW安装步骤

    Adobe Dreamweaver CC 2015破解步骤 Adobe Dreamweaver CC 2015的安装包和破解补丁可以在这里下载.链接: http://pan.baidu.com/s/1 ...

  4. 16090202(剑灵GPA)

    [目标] 剑灵GPA [思路] 1 2 绘制角色DrawCall body 5526面片 2.1[第一个DrawCall]63 RT 这个DrawCall PS VS 参数列表 VS // // Ge ...

  5. 禁止浏览.htaccess文件

    很多黑客会攻击和利用.htaccess做网站跳转,所以保护好.htaccess文件尤为重要. 在apache的httpd.conf的配置文件中 默认是已经设置了禁止对.htaccess的访问,截取相关 ...

  6. spark示例

    1)java(App.java) package com.ejiajie.bi.hello; import org.apache.spark.api.java.JavaSparkContext; im ...

  7. maven pom.xml

    什么是pom?    pom作为项目对象模型.通过xml表示maven项目,使用pom.xml来实现.主要描述了项目:包括配置文件:开发者需要遵循的规则,缺陷管理系统,组织和licenses,项目的u ...

  8. 关于ssh上传文件

    今天用ssh传项目到公司总部的服务器上,报了错误: encountered 1 errors during the transfer 重启ssh再次上传还是一样的错误,然后我让公司那里重启一下服务器, ...

  9. jquery.qrcode 生成二维码带logo

    <div id="container">这里是二维码显示位置</div> <script language="JavaScript" ...

  10. Retrofit源码研究

    2016-05-06 15:35:27 最近抽空研究了一下Retrofit源码,包括API使用.源码结构.使用到的设计模式.SDK的架构设计.作者设计/实现思路等,会形成一系列文章. 以前Retrof ...