1、模式分类

1.1  从目的来看:

•      – 创建型(Creational)模式:负责对象创建。

•      – 结构型(Structural)模式:处理类与对象间的组合。

•      – 行为型(Behavioral)模式:类与对象交互中的职责分配。

1.2 从范围来看:

•     – 类模式处理类与子类的静态关系。

•     – 对象模式处理对象间的动态关系。

2、动机(Motivation)目的

在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。

3、意图(Intent)

保证一个类仅有一个实例,并提供一个该实例的全局访问点。

——《设计模式》GoF

4、单例模式多种实现方法

4.1 单线程Singleton 模式实现

  class Singleton
{
private static Singleton instance;
private Singleton() //防止外界随意new此对象,如果访问级别设置成protected,那么子类可以派生,同时也也不可以实例化此对象
{
}
public static Singleton Instance
{
get {
if (instance == null) //起到延迟加载对象的作用,当用户用不到此实例的时候
{
instance = new Singleton();
}
return instance;
}
}
}

单线程Singleton模式的几个要点
                  • Singleton模式中的实例构造器可以设置为protected以允许子类派生。(同样不可实例化对象,受保护级别限制)
                  • Singleton模式一般不要支持ICloneable接口(实例克隆),因为这可能会导致多个对象实例,与Singleton模式的初衷违背。(实现了ICloneable接口,就必须实现Clone()方法,在此方法中我们可以返回新的对象,这样就与Singleton模式相违背了!)
                  • Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。(构造对象的方式:可以通过构造器,也可以通过序列化构造对象,序列化出来的对象和原来的对象地址是不一样的,是完全的深拷贝方式(创建新的对象))
                  • Singletom模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。
          (缺点)• 不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singleton类的多个实例对象。(在上面的代码第10行进行if判断的时候,假设现在有两个线程(A,B)同时执行到了此行,当A线程进行if判断,此时判断为null,就去实例化对象,但是A线程还没来得及进行对象的实例化的时候,此时B线程就进行了if的判断,并完成了对此对象的判断,判断为null,所以B线程就会去创建另一个实例,所以就创建了两个实例!)

4.2、多线程Singleton 模式实现

 class Singleton
{
private static volatile Singleton instance = null; //volatile(编译器在对代码进行编译的时候,会对代码进行一些微调,对代码的顺序进行调整,
volatile关键字就保证了编译器不会对instance进行代码的微调,
这样就保证了严格意义上的多线程不会出现创建出多个实例的情况)
private static object lockHelper = new object(); //辅助器
private Singleton() //防止外界随意new此对象
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (lockHelper)
{
if (instance == null)//双检查
{
instance = new Singleton();
}
}
}
return instance;
}
}
}

优缺点:这种实现方式对多线程来说是安全的,同时线程不是每次都加锁,只有判断对象实例没有被创建时它才加锁(如果最外层的if不加的话,那么其他线程都会进行加锁操作,会增加额外的开销,损失性能),加锁后还得再进行对象是否已被创建的判断。它解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。它还允许您将实例化延迟到第一次访问对象时发生。

volatile:

MSDN上的解释:volatile 关键字表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值

4.3、 使用.NET类型初始化机制实现多线程Singleton 模式(最好的方式)

    sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton() //防止外界随意new此对象
{
}
}

其实上面的代码实现如果展开来的话等同于下面代码的实现

   sealed class Singleton
{
private static readonly Singleton instance;
static Singleton() //在调用instance静态字段时会先去执行此静态构造器,静态构造器能保证多线程环境下只有一个线程执行了此静态构造器,为我们自动加锁
{
instance = new Singleton();//在静态构造器中实例化
}
private Singleton() //防止外界随意new此对象
{
}
}

该类标记为 sealed 以阻止发生派生,而派生可能会增加实例。此外,变量标记为 readonly,这意味着只能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。

缺点:

  • 我们对实例化机制的控制权较少!在4.1和4.2中能够在实例化之前使用非默认的构造函数或执行其他任务。由于在此实现方法中由 .NET Framework负责执行初始化,因此您没有这些选项。
  • 无法实现延迟初始化,
  • 4.3的实现方法无法进行传参,4.1和4.2的实现方式都可以进行传参,主要是因为对象的实例化是在方法内部创建的(属性实质为方法),所以我们可以把属性写成带参数的方法即可!如下,对4.1方法变为带参数的!
  class Singleton
{
private static Singleton instance;
public string Name { get; set; }
public int Age { get; set; }
public static Singleton GetInstance(string name, int age)
{
if (instance == null)
{
instance = new Singleton(name, age);
}
return instance;
}
private Singleton(string name, int age)
{
this.Name = name;
this.Age = age;
}
}

5、延迟初始化

 public sealed class Singleton
{
Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}

这里,初始化工作有Nested类的一个静态成员来完成,这样就实现了延迟初始化,并具有很多的优势,是值得推荐的一种实现方式

6、Singleton模式扩展
            • 将一个实例扩展到固定几个实例,例如对象池的实现。这样做是允许的而且是有意义的!
            • 将new 构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的一个实例。
            • 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的实例构造器的任意调用”。

7、.NET框架中的Singleton应用

  • winform程序,你只需要点击按钮,弹出一个窗口,并且保证此窗口只能有一个!再点击按钮是无法在弹出此窗体的!
  • PC机中可能有几个串口,但只能有一个COM1口的实例。
  • 系统中只能有一个窗口管理器。
  • .NET Remoting中服务器激活对象中的Sigleton对象,确保所有的客户程序的请求都只有一个实例来处理。

8、推荐参考书
            • 《设计模式:可复用面向对象软件的基础》GoF                             --小白看起来会有点困难
            • 《面向对象分析与设计》Grady Booch                                       --翻译有些问题
            • 《敏捷软件开发:原则、模式与实践》Robert C. Martin
            • 《重构:改善既有代码的设计》 Martin Fowler
            • 《Refactoring to Patterns》Joshua Kerievsky                         --没中文版

9、参考

《C#面向对象设计模式纵横谈》    李建忠

http://terrylee.cnblogs.com    TerryLee

作者:MrZivChu

2013-08-02 15:34:03

Singleton patterns 单件(创建型模式)的更多相关文章

  1. 设计模式01: Singleton 单例模式(创建型模式)

    Singleton 单例模式(创建型模式) 动机(Motivation)当进行软件开发是会有这样一种需求:在系统中只有存在一个实例才能确保它们的逻辑正确性.以及良好的效率.这应该是类设计者的责任,而不 ...

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

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

  3. 设计模式之美:Creational Patterns(创建型模式)

    创建型模式(Creational Patterns)抽象了对象实例化过程. 它们帮助一个系统独立于如何创建.组合和表示它的那些对象. 一个类创建型模式使用继承改变被实例化的类. 一个对象创建型模式将实 ...

  4. 设计模式学习之单例模式(Singleton,创建型模式)(4)

    假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢? 第一步: 新建一个Person类,类中 ...

  5. .NET设计模式(7):创建型模式专题总结(Creational Pattern)(转)

    概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独立于如何创建.组合和表示它的那些对象.本文对五种常用创建型模式进行了比较,通过一个游戏开发场景的例子来说该如何使用创建型模 ...

  6. .NET设计模式(7):创建型模式专题总结(Creational Pattern)

    ):创建型模式专题总结(Creational Pattern)    创建型模式专题总结(Creational Pattern) --.NET设计模式系列之七 Terrylee,2006年1月 转载: ...

  7. Java 23种设计模式详尽分析与实例解析之一--创建型模式

    面向对象的设计原则 常用的面向对象设计原则包括7个,这些原则并不是独立存在的,它们相互依赖.互为补充. Java设计模式 创建型模式 简单工厂模式 模式动机: 考虑一个简单的软件应用场景,一个软件系统 ...

  8. NET设计模式 第二部分 创建型模式(6):创建型模式专题总结(Creational Pattern)

    创建型模式专题总结(Creational Pattern) ——.NET设计模式系列之七 Terrylee,2006年1月 概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统 ...

  9. [19/04/22-星期一] GOF23_创建型模式(单例模式)

    一.概念 <Design Patterns: Elements of Reusable Object-Oriented Software>(即后述<设计模式>一书),由 Eri ...

随机推荐

  1. 贪心,二叉树搜索,ZOJ(2315)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1315 解题报告: #include <stdio.h> ...

  2. 轻量级HTTP服务器Nginx(常用配置实例)

    轻量级HTTP服务器Nginx(常用配置实例)   文章来源于南非蚂蚁   Nginx作为一个HTTP服务器,在功能实现方面和性能方面都表现得非常卓越,完全可以与Apache相媲美,几乎可以实现Apa ...

  3. JS面向对象、prototype、call()、apply()

    一. 起因 那天用到prototype.js于是打开看看,才看几行就满头雾水,原因是对js的面向对象不是很熟悉,于是百度+google了一把,最后终于算小有收获,写此纪念一下^_^. prototyp ...

  4. CCF CSP 201712-2 游戏

    题目链接:http://118.190.20.162/view.page?gpid=T67 问题描述 有n个小朋友围成一圈玩游戏,小朋友从1至n编号,2号小朋友坐在1号小朋友的顺时针方向,3号小朋友坐 ...

  5. [转] JAVA中读取网络中的图片资源导入到EXCEL中

    需求 导出人员的信息并且加上人员的照片至EXCEL中 完整的代码 //创建一个表格 HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb ...

  6. npy数据的保存与读取

    保存 利用这种方法,保存文件的后缀名字一定会被置为.npy x = numpy.save("data_x.npy",x) 读取 data = numpy.load("da ...

  7. LeetCode(Two Sum)

    一.题目要求 Given an array of integers, return indices of the two numbers such that they add up to a spec ...

  8. 第10章 新建工程-库函数版—零死角玩转STM32-F429系列

    第10章     新建工程—库函数版 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...

  9. django ORM单表操作

    1.ORM介绍 ORM是“对象-关系-映射”的简称 映射关系: mysql---------Python 表名----------类名 字段----------属性 表记录--------实例化对象 ...

  10. wm_concat()函数

    工作中遇到这样一个问题,一张数据库表中有一个字段file_id,还有一个主键f_id(唯一),而file_id不唯一,我想把file_id=‘123456789’的记录中的f_id(主键)连接成一个字 ...