一、简介

单例模式主要用的作用是用于保证程序运行中某个类只有一个实例,并提供一个全局入口点。单例模式(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. docker部署netcore应用(二)

    基于第一章已经安装好了docker,这次将把netcore应用部署到docker容器中 开发工具vs2017,准备个DotNet Core的Console应用程序,测试一下 发布DockerTest项 ...

  2. webpack单独构建scss文件与.vue组件里构建scss的一个坑

    在入口main.js里构建scss是通过引入模块的方式 import './assets/_reset.scss'; import './assets/_flex.scss'; import './a ...

  3. java开发环境配置(windows下JDK7+tomcat7)

    參考原文:http://www.cnblogs.com/goto/archive/2012/11/16/2772683.html http://www.cnblogs.com/feilong35407 ...

  4. zxl2431 指向函数的指针

    (一) 用函数指针变量调用函数 可以用指针变量指向整形变量.字符串.数组.结构体.也可以指向一个函数.一个函数在编译时被分配一个入口地址.这个入口地址就称为函数指针.可以用一个指针变量指向函数,然后通 ...

  5. JavaScript动态广告弹出框

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. Windows 10 子系统Linux重启(不重启Win10)

    Using CMD (Administrator) net stop LxssManager net start LxssManager

  7. 取消scrollView上下拉升

    if (ios_Vewsion_5_Or_Above) { _scrollView.bounces = NO; } else { for (id subview in _scrollView.subv ...

  8. 相关web 片段记录安全性研究(不时更新)

    一.有关html/css, js, php, cgi 的一些认识 当我们浏览器訪问一个网站的静态文件.会把文件内容都下载下来(一般压缩).当然假设遇到外联的css/js,会再发起请求得 到.假设我们右 ...

  9. .net reactor 学习系列(四)---.net reactor应用场景

    原文:.net reactor 学习系列(四)---.net reactor应用场景         前面已经学习了.net reactor一些基础知识,现在准备学习下实际的应用场景,只是简单的保护和 ...

  10. 在Keystone V3基础上改进的分布式认证体系

    目标 使用java实现keystone v3相关功能与概念: api client authentication service discovery distributed multi-tenant ...