一、简介

单例模式主要用的作用是用于保证程序运行中某个类只有一个实例,并提供一个全局入口点。单例模式(Singleton)为GOF阐述的标准24种设计模式中最简单的一个。但随着时间推移,GOF所阐述的单例实现已不能完全满足实际应用。

"ensure a class has only one instance, and provide a global point of access to it"

二、动机(应用场景)

几乎在每个应用程序中,都需要有一个从中进行全局访问和维护某种类型数据的区域。 在面向对象的 (OO) 系统中也有这种情况,在此类系统中,在任何给定时间只应运行一个类或某个类的一组预定义数量的实例。

1、当使用某个类来维护增量计数器时,此简单的计数器类需要跟踪在多个应用程序领域中使用的整数值。 此类需要能够增加该计数器并返回当前的值。 对于这种情况,所需的类行为应该仅使用一个类实例来维护该整数,而不是使用其它类实例来维护该整数。
2、每台计算机可以有若干个打印机,但只能有一个Printer Spooler,避免两个打印作业同时输出到打印机。
3、PC机中可能有几个串口,但只能有一个COM1口的实例。
4、系统中只能有一个窗口管理器。
5.NET Remoting中服务器激活对象中的Sigleton对象,确保所有的客户程序的请求都只有一个实例来处理。
6.应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。

三、C#实现

1、单线程实现

单线程单例模式实现/**
*单例模式的单线程实现。无法保证单线程模式下只产出唯一的一个实例。
*/
Class Singleton
{
private static Singleton Instance;
//将构造函数定义为private防止该类在外部被实例化
//如需有将此类定义可继承的,则可将private更改为protected
private Singleton(){} public static Singleton GetInstance()
{
//当处于多线程环境时,可能存在多个线程在由于代码执行的顺序导致
//多个线程生成多个实例,而违背该模式的初衷
if(Instance==null)
{
Instance=new Singleton();
}
return Instance;
}
}

可以说是一个标准的单例的代码。

优点:

  • 由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能(例如,对子类进行实例化),即使它可能引入不想要的依赖性。

  • 直到对象要求产生一个实例才执行实例化;这种方法称为"懒实例化"。懒实例化避免了在应用程序启动时实例化不必要的 singleton

缺点:

多线程环境下它是不安全的。如果执行过程的不同线程同时进入 Instance 属性方法,那么可能会创建多个 Singleton 对象实例。每个线程都会执行下列语句,并决定必须创建新的实例。

2、多线程实现

多线程单例模式实现class Singleton
{
//volatile关键字。 这应该告诉编译器不要对代码重新排序,并且放弃优化。确保只有在实例变量分配完成后才能访问实例变量。
//防止由于编译器优化导致代码控制失效.
private static volatile Singleton instance;
//使用 syncRoot 实例来进行锁定(而不是锁定类型本身),以避免发生死锁。
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
//双重检验锁定- Double-Check Locking
// double-check locking 方法解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}

优点:由于实例的产生由自己控制,可以对非默认构造函数进行扩展、传参等操作。

缺点:实现相对复杂

3、C#简洁版

由于 C# 与公共语言运行库也提供了一种"静态初始化"方法,这种方法不需要开发人员显式地编写线程安全代码,即可解决多线程创建等问题。

简洁实现1public sealed class Singleton
{
//变量标记为 readonly,这意味着只能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。
private static readonly Singleton instance = new Singleton();
private Singleton(){}
public static Singleton Instance
{
get
{
return instance;
}
}
}

更简洁的方式:

简洁实现1public sealed class Singleton
{
public static readonly Singleton Instance = new Singleton();
private Singleton(){}
}

因为静态构造函数是属于类的,而不属于任何一个实例,所以这个构造函数只会被执行一次,而且是在创建此类的第一个实例或引用任何静态成员之前,由.NET自动调用。

1、由于静态构造函数由.NET调用,所以不需要public和private等访问修饰符。

2、在创建第一个类实例或任何静态成员被引用时,.NET将自动调用静态构造函数来初始化类。(我们无法调用,也不知道它何时被调用)

3、静态构造函数属于类,构造函数属于实例,他们并不冲突。静态构造函数只会运行一次。

缺点:由于在此解决方案中由 .NET Framework 负责执行初始化,无法在实例化之前使用非默认的构造函数或执行其他任务。在大多数情况下,静态初始化是在.NET 中实现 Singleton 的首选方法。

四、总结

单线程版、多线程版、简洁版有各自的应用,没有那种实现是最好的。

总结上述三种实现方法,以是否需要在创建单例实例时传参或执行其他任务分两类。即:

1、不需要执行其他任务

使用简洁版即可以保障在单线程、多线程都能安全使用的同时,代码量较少。

2、需要

一般情况下,均为单线程版。则使用单线程创建。若程序有多线程应用则应用使用双重检测的多线程实现。

参考文档:

http://msdn.microsoft.com/zh-cn/library/ff650316.aspx

http://terrylee.cnblogs.com/archive/2005/12/09/293509.html

第一式、单例模式-Singleton模式(创建型)的更多相关文章

  1. 单例模式/singleton模式/创建型模式

    Java实现要点: 私有构造方法 线程安全(并发的考虑) 延迟加载(效率的考虑,对于较大的类在使用时在加载) 公有方法访问单一实例 常见单例模式代码及问题 //无延迟加载,常驻内存(即使不使用) cl ...

  2. 设计模式(二)单例模式Singleton(创建型)

    几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的.您希望在应用程序中共享数据库句柄,因为在保持连接打开或关闭时,它是一种开销.再如大家最经常用的IM, ...

  3. 设计模式-单例模式(Singleton) (创建型模式)

    //以下代码来源: 设计模式精解-GoF 23种设计模式解析附C++实现源码 //Singleton.h #pragma once #include<iostream> class Sin ...

  4. 设计模式--单例模式Singleton(创建型)

    单例模式很显然是定义一个类,这个类在程序中只有唯一的实例对象.一般单例类的构造函数是私有的,只能通过调用静态函数GetInstance来获取实例. 一.单例模式有三种:懒汉式单例.饿汉式单例.登记式单 ...

  5. C#面向对象设计模式纵横谈——2.Singleton 单件(创建型模式)

    一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配 ...

  6. FactoryMethod工厂方法模式(创建型模式)

    1.工厂方法模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只 ...

  7. Prototype原型模式(创建型模式)

    1.原型模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只有一 ...

  8. 6、单例模式 Singleton模式 只有一个实例 创建型模式

    1.了解Singleton模式 程序在运行时,通常都会生成很多实例.例如,表示字符串的java . lang . string类的实例与字符串是- -对- -的关系,所以当有1000个字符串的时候,会 ...

  9. 设计模式(二)单件模式Singleton(创建型)

    SINGLETON(单件)—对象创建型模式 几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的.您希望在应用程序中共享数据库句柄,因为在保持连接打开或关 ...

  10. 设计模式(六):Singleton 单件模式 -- 创建型模式

    1.定义 当需要控制一个类的实例数量且调用者可以从一个公共的访问点访问时. 2.适用场景 1. 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时. 2. 当这个唯一实例应该是通过子类化可扩 ...

随机推荐

  1. WPF 拼音输入法

    原文:WPF 拼音输入法 本文来告诉大家如何使用 WPF 来写一个输入法,使用的方式是钩子. 目录 键盘 解析键盘 获得按键 输入流向 算法 实际上本文是在使用一个好用的软件 希沃白板 的时候发现在里 ...

  2. HDU 1143 Tri Tiling (递推)

    Tri Tiling Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  3. C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口

    原文:C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http ...

  4. VS2015如何自定义类模板、我的模板——原来这么简单!

    在前一段时间忽然想给自己电脑上的vs新建类的时候添加一个自定义个注释,但是在网上搜了很久都是说vs2012之类的方法系统也都是win7.XP之类的独独没有win8的.故此自己不断的尝试修改发现方法如下 ...

  5. python 教程 第九章、 类与面向对象

    第九章. 类与面向对象 1)    类 基本类/超类/父类被导出类或子类继承. Inheritance继承 Inheritance is based on attribute lookup in Py ...

  6. 3DMax模型输入到WPF中运行

    原文:3DMax模型输入到WPF中运行 其实看看笔者文章之前,可以在网上搜索下将3Dmax模型输入到WPF的办法,大部分结果都是这篇文章.这篇文章呢?有点麻烦,就是我们3Dmax模型转换到Blend的 ...

  7. 怎么快速构建自己的C/C++程序?——有关编译、静态链接和SCons

    怎么快速构建自己的C/C++程序?--有关编译.静态链接和SCons 1. 写在前面 最初写C++是在Visual Studio这个IDE里,那时我并没有makefile的概念,对程序的编译和链接的一 ...

  8. blockchain_eth客户端安装 & geth使用 &批量转账(一)

    这里是第一篇,主要讲eth客户端安装 eth官网 https://ethereum.org/ 国内有一个论坛内容挺多的,可以参考  http://ethfans.org/ eth客户端: eth客户端 ...

  9. wpf Content数据绑定StringFormat起作用的原理和解决

    原文:wpf Content数据绑定StringFormat起作用的原理和解决 <Window x:Class="WpfOne.Bind.Bind6" xmlns=" ...

  10. WPF 自定义验证规则

    <Window x:Class="DataBindingExam.MainWindow"        xmlns="http://schemas.microsof ...