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代码读取 ...
随机推荐
- 周爱民:真正的架构师是没有title的(图灵访谈)
周爱民,现任豌豆荚架构师,国内软件开发界资深软件工程师.从1996年起开始涉足商业软件开发,历任部门经理.区域总经理.高级软件工程师.平台架构师等职,有18年的软件开发与架构.项目管理及团队建设经验, ...
- gulp教程之gulp-livereload
简介: gulp-livereload拯救F5!当监听文件发生变化时,浏览器自动刷新页面.[事实上也不全是完全刷新,例如修改css的时候,不是整个页面刷新,而是将修改的样式植入浏览器,非常方便.]特别 ...
- Java—泛型
泛型是JDK 5 中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型.泛型本质是参数化类型,也就是所操作的数据类型指定为一个参数. 假定我们有这样一个需求: ...
- 网站优化之PHPCMS如何开启伪静态
做为一名网站优化方面的工作,那么选择CMS系统的时候,有良好的网站优化功能就是一个好的CMS的标准之一,而系统是否支持伪静态,则是URL优化的工作之一,而PHPCMS是一款网站优化方面做得比较成功的C ...
- C# Request中修改header信息
var headers = app.Context.Request.Headers; Type hdr = headers.GetType(); PropertyInfo ro = hdr.GetPr ...
- 理解js中__proto__和prototype的区别和关系
首先,要明确几个点:1.在JS里,万物皆对象.方法(Function)是对象,方法的原型(Function.prototype)是对象.因此,它们都会具有对象共有的特点.即:对象具有属性__proto ...
- Spring(4)
Spring的Bean的配置形式 1.基于XML的形式(无需讲解) 2.基于注解的形式(需要引入AOP的jar包,此jar包实现了AOP的注解) 当在Spring配置文件中引入类扫描注解命名空间并且指 ...
- listview指定某item的点击效果
需求:listview的某些item能够点击,需要点击效果,有些item不能点击,需要屏蔽点击效果. 实现: 1.layout: <ListView android:id="@+id/ ...
- php 常用数组操作
php常用的数组操作函数,包括数组的赋值.拆分.合并.计算.添加.删除.查询.判断.排序等 array_combine 功能:用一个数组的值作为新数组的键名,另一个数组的值作为新数组的值 <?p ...
- php的__clone __call
(1) __clone方法在一个对象赋值给另外的一个对象的时候自动调用 <?php class A { public $a = "aa"; public $b = 10; f ...