一、简介

单例模式主要用的作用是用于保证程序运行中某个类只有一个实例,并提供一个全局入口点。单例模式(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. 关于hexo的SEO的好文章

    1.hexo高阶教程:想让你的博客被更多的人在搜索引擎中搜到吗? 2.Hexo Seo优化让你的博客在google搜索排名第一 3.hexo 博客 seo 优化 4.HEXO SEO 高级优化 5.H ...

  2. vuex与vue-router学习方案

    1.vuex,官方vuex2.0的文档写得太简略了,先1.0的文档,研究1.0分支的counter例子.1.0文档只需看核心概念和API参考文档.2.0的用法先不管,需要的时候再说,先把1.0高熟练. ...

  3. IIS与TOMCAT协同工作---在IIS下运行JSP页面

    转载:http://www.cnblogs.com/sjpisaboy/archive/2006/12/07/585749.html 最近碰到一个问题:我们实验室的一台IBM EServer服务器被运 ...

  4. Parallel.For

    Parallel.For 你可能忽视的一个非常实用的重载方法    说起Parallel.For大家都不会陌生,很简单,不就是一个提供并行功能的for循环吗? 或许大家平时使用到的差不多就是其中最简单 ...

  5. $.extend(true,{},a,b)解析

    原文:$.extend(true,{},a,b)解析 版权声明: https://blog.csdn.net/bsfz_2018/article/details/81738437 什么是$.exten ...

  6. WPF中使用AxisAngleRotation3D实现CAD的2D旋转功能

    原文:WPF中使用AxisAngleRotation3D实现CAD的2D旋转功能       对于CAD图形来说,3D旋转比较常用,具体实现方法在上篇文章<WPF中3D旋转的实现 >中做了 ...

  7. Linux性能测试 dmesg命令

    dmesg 命令主要用来显示内核信息.使用 dmesg 可以有效诊断机器硬件故障或者添加硬件出现的问题.  另外,使用 dmesg 可以确定您的服务器安装了那些硬件.每次系统重启,系统都会检查所有硬件 ...

  8. [转] css3制作图形大全

    Square   #square {     width: 100px;     height: 100px;     background: red; } Rectangle   #rectangl ...

  9. Fidder模拟发送请求

    在Fiddler的Composer一栏,可以模拟请求 举例 首先通过浏览器访问页面http://baidu.com/ ,在右侧可以拿到请求情况 在Inspectors一栏可以看到请求和响应结果,复制请 ...

  10. 不得不说,我太佩服node了,连openXML也搞定了!

    https://github.com/Ziv-Barber/officegen 开源项目地址 使用报告等有空完成!