C# 单例模式的五种写法
1、简单实现
C#
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public sealed class Singleton
{
static Singleton instance = null;
public void Show()
{
Console.WriteLine( "instance function");
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
|
评注:
对于线程来说不安全
单线程中已满足要求
优点:
由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能
直到对象要求产生一个实例才执行实例化;这种方法称为“惰性实例化”。惰性实例化避免了在应用程序启动时实例化不必要的 singleton。
2、线程的安全
C#
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public sealed class Singleton
{
static Singleton instance = null;
private static readonly object padlock = new object();
private Singleton()
{
}
public static Singleton Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
}
}
return instance;
}
}
}
|
评注:
同一个时刻加了锁的那部分程序只有一个线程可以进入
对象实例由最先进入的那个线程创建
后来的线程在进入时(instence == null)为假,不会再去创建对象实例
增加了额外的开销,损失了性能
3、双重锁定
C#
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public sealed class Singleton
{
static Singleton instance = null;
private static readonly object padlock = new object();
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
|
评注:
多线程安全
线程不是每次都加锁
允许实例化延迟到第一次访问对象时发生
4、静态初始化
C#
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public sealed class Singleton
{
private static readonly Singleton instance = null;
static Singleton()
{
instance = new Singleton();
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
|
评注:
依赖公共语言运行库负责处理变量初始化
公共静态属性为访问实例提供了一个全局访问点
对实例化机制的控制权较少(.NET代为实现)
静态初始化是在 .NET 中实现 Singleton 的首选方法
小注:
静态构造函数既没有访问修饰符,C#会自动把他们标记为private,之所以必须标记为private,是为了阻止开发人员写的代码调用它,对它的调用总是由CLR负责的。


5、延迟初始化
C#
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public sealed class Singleton
{
private Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
public static void Hello()
{
}
private class Nested
{
internal static readonly Singleton instance = null;
static Nested()
{
instance = new Singleton();
}
}
}
|
评注:
初始化工作由Nested类的一个静态成员来完成,这样就实现了延迟初始化。
由于静态函数的调用时机,是在类被实例化或者静态成员被调用的时候进行调用,并且是由.net框架来调用静态构造函数来初始化静态成员变量,所以,如果按照写法四来写,再调用Hello方法的时候,就会实例化出来Singleton实例,这不是我们想看到的,因为我们有可能只是想用Hello方法,而不是别的。
注意事项:
1、Singleton模式中的实例构造器可以设置为protected以允许子类派生。
2、Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
3、Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
4、Singletom模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。
总结:
1、Singleton模式是限制而不是改进类的创建。
2、理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。
3、可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。
C# 单例模式的五种写法的更多相关文章
- 单例模式的N种写法
单例模式算是设计模式中最容易理解,也是最容易手写代码的模式了吧.但是其中的坑却不少,所以也常作为面试题来考.本文主要对几种单例写法的整理,并分析其优缺点.很多都是一些老生常谈的问题,但如果你不知道如何 ...
- Java:单例模式的七种写法(转载)
第一种(懒汉,线程不安全): package Singleton; /** * @echo 2013-10-10 懒汉 线程不安全 */ public class Singleton1 { priva ...
- Java:单例模式的七种写法[转]
第一种(懒汉,线程不安全): 1 public class Singleton { 2 private static Singleton instance; 3 privat ...
- 【JAVA学习】单例模式的七种写法
尊重版权:http://cantellow.iteye.com/blog/838473 第一种(懒汉.线程不安全): Java代码 public class Singleton { private ...
- KandQ:单例模式的七种写法及其相关问题解析
设计模式中的单例模式可以有7种写法,这7种写法有各自的优点和缺点: 代码示例(java)及其分析如下: 一.懒汉式 public class Singleton { private static Si ...
- Java设计模式之单例模式(七种写法)
Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...
- Java:单例模式的七种写法<转>
第一种(懒汉,线程不安全): 1 public class Singleton { 2 private static Singleton instance; 3 privat ...
- Java 单例模式的七种写法
Java 单例模式的七种写法 第一种(懒汉,线程不安全) public class Singleton { private static Singleton instance; private Sin ...
- 温故而知新(java实现)单例模式的七种写法
第一种(懒汉,线程不安全): Java代码 public class Singleton { private static Singleton instance; private Singleton ...
随机推荐
- 进程实时监控pidstat命令详解
pidstat主要用于监控全部或指定进程占用系统资源的情况,如CPU,内存.设备IO.任务切换.线程等.pidstat首次运行时显示自系统启动开始的各项统计信息,之后运行pidstat将显示自上次运行 ...
- Android使用VideoView播放本地视频及网络视频Demo
1.xm文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:and ...
- int 和 Integer 的区别
1.两个New生成的Integer 永远不相等,因为他们的内存地址不相等 2.如果一个是New生成的Integer 另一个是通过赋值生成的话,如果值相等那么他们相等,因为这时Integer会通过自动拆 ...
- MySQL之多表查询练习 与基本查询基础
MySQL 增删查改 一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [into]<表名> [列名] values <列值> 例:insert i ...
- UVA-816.Abbott's Tevenge (BFS + 打印路径)
本题大意:给定一个迷宫,让你判断是否能从给定的起点到达给定的终点,这里起点需要输入起始方向,迷宫的每个顶点也都有行走限制,每个顶点都有特殊的转向约束...具体看题目便知... 本题思路:保存起点和终点 ...
- Codeforces Round #450 (Div. 2)
Codeforces Round #450 (Div. 2) http://codeforces.com/contest/900 A #include<bits/stdc++.h> usi ...
- TZOJ 2725 See you~(二维树状数组单点更新区间查询)
描述 Now I am leaving hust acm. In the past two and half years, I learned so many knowledge about Algo ...
- f5会话保持导致站点访问故障
1.环境: vs Service Port为443和80,vip为10.160.100.66,pool为10.160.45.42/43的8080.80的vs重新到443. 2.问题: 单独访问源站都没 ...
- Python: print stdout同行输出
项目中发现,PyCharm运行youtube_dl下载,其进度在同行显示,即替换上行输出. 稍做研究,记录下来: #coding=utf-8 from __future__ import print_ ...
- java_14.1 判断是否是闰年
package demo; import java.util.Calendar; import java.util.Scanner; public class Demo { public static ...