第一式、单例模式-Singleton模式(创建型)

一、简介

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

第一式、单例模式-Singleton模式(创建型)

时间: 2024-08-11 17:22:07

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

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

几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的.您希望在应用程序中共享数据库句柄,因为在保持连接打开或关闭时,它是一种开销.再如大家最经常用的IM,如QQ,在同一台电脑,一个帐号只能有唯一的登录. 1. 问题 怎样确保一个特殊类的实例是独一无二的(它是这个类的唯一实例),并且这个实例易于被访问呢? 2. 解决方案 1)全局变量:一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象.因为你的任何代码都能修改全局变量,这将不可避免的引起

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

一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配. 从范围来看: 类模式处理类与子类的静态关系. 对象模式处理对象间的动态关系. 二:Singleton (创建型模式) 单件 1.动机(Motivation) 软件系统中,经常有这样一些特殊的类,必须保证他们在系统中只存在一个实例,才能确保它们的逻辑正确性,以及良好的效率. 如何绕过常规的构造器,

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

1.定义 当需要控制一个类的实例数量且调用者可以从一个公共的访问点访问时. 2.适用场景 1. 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时. 2. 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时. 3.评价 优点: 1. 对唯一实例的受控访问, 因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它. 2. 缩小名空间,Singleton模式是对全局变量的一种改进.它避免了那些存储唯一实例的全局变量污染名空

单例和原型模式-创建型

单例模式 确保一个特殊类的实例是独一无二的(它是这个类的唯一实例),并且这个实例易于被访问. 解决方案 1)全局变量:一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象.因为你的任何代码都能修改全局变量,这将不可避免的引起更多调试的意外.换句话说,全局变量的状态总是会出现一些问题的. 2)类构造函数私有和类自身的静态方法:让类自身负责保存它的唯一实例(静态变量).这个类可以保证没有其他实例可以被创建(通过截取创建新对象的请求) ,并且它可以提供一个访问该实例的方法(静态方法).这就

设计模式(五):PROTOTYPE原型模式 -- 创建型模式

1.定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 2.适用场景 原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对象的副本,这种创建对象的方式,相比我们之前说的几类创建型模式还是有区别的,之前的讲述的工厂模式与抽象工厂都是通过工厂封装具体的new操作的过程,返回一个新的对象,有的时候我们通过这样的创建工厂创建对象不值得,特别是以下的几个场景的时候,可能使用原型模式更简单也效率更高. • 1)当一个系统应该独立于

设计模式(三): FACTORY工厂模式 -- 创建型模式

1.定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类. 2.适用场景 1.第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来.Java Collection中的iterator() 方法即属于这种情况. 2.第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给

设计模式(四):SIMPLE FACTORY简单工厂模式 -- 创建型模式

1.定义 简单工厂模式又称静态工厂方法模式.重命名上就可以看出这个模式一定很简单.它存在的目的很简单:定义一个用于创建对象的接口. 2.适用场景 如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用.后来出现工业革命.用户不用去创建宝马车.因为客户有一个工厂来帮他创建宝马.想要什么车,这个工厂就可以建.比如想要320i系列车.工厂就创建这个系列的车.即工厂可以创建产品. 3.评价 优点: 工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体

设计模式(二): BUILDER生成器模式 -- 创建型模式

1.定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 2.适用场景 1. 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 2. 当构造过程必须允许被构造的对象有不同表示时. 3.评价 1. 它使你可以改变一个产品的内部表示. Builder对象提供给导向器一个构造产品的抽象接口.该接口使得生成器可以隐藏这个产品的表示和内部结构.它同时也隐藏了该产品是如何装配的.因为产品是通过抽象接口构造的,你在改变该产品的内部表

设计模式(一): abstract factory抽象工厂模式 -- 创建型模式

1.定义 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 2.适用场景 1.一个系统要独立于它的产品创建.组合和表示. 2.一个系统要由多个产品系列中的一个来配置. 3.当你要强调一系列相关的产品对象的设计以便进行联合使用. 4.当你提供一个产品类库,而只想显示它们的接口而不是实现. 3.评价 1.它分离了具体的类 2.它使得易于交换产品系列 3.它有利于产品的一致性 4.难以支持新种类的产品 5."开放-封闭"原则要求系统对扩展开放,对修改封闭.通过扩展达到增