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. hdu-2688 Rotate---树状数组+模拟

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2688 题目大意: 给你n数,(n<=3e6),有两个操作,Q为 当前有多少对数,满足严格递增, ...

  2. querystring处理参数小利器

    相信上一章的讲解,相信大家对url地址有一个更直观的认识,在url解析的时候可以用querystring这样一个module替换,然后对这个query集成一个对象,这里不管是前端开发还是后端开发,都常 ...

  3. first 和firstordefault的用法 简介

    https://www.cnblogs.com/1312mn/p/9212325.html

  4. python——文件处理

    1.文件处理 f = open(file="file01.txt", mode="r", encoding="utf-8") #python ...

  5. 前端jQuery之事件流

    1.事件流概念 描述的是从页面中接收事件的顺序 包含事件捕获阶段,处于目标阶段,事件冒泡阶段 2.绑定事件 语法 bind(type,data,fn) 示例:每个标签被点击的时候,弹出其文本 $(&q ...

  6. JQuery 过滤选择器 与属性修改的方法演示比较

    文本匹配 在表单输入项里面输入值,根据输入值,点击判断按钮,让对应的复选框选中 <html> <head> <meta http-equiv="Content- ...

  7. centos6 下查看SELinux状态 关闭SELinux

    转载自:https://blog.csdn.net/boomjane_testingblog/article/details/52859977 SELinux(Security-Enhanced Li ...

  8. Redis 4.0 从节点写入不同步问题

    redis4.0出现了很多新的特性,删除键值unlink,slowlog记录来源ip.内存统计信息等.其中一个重要的同步祭祀是Psync2.psync2主要让redis在从实例重启和主实例故障切换场景 ...

  9. RPC框架基础概念理解以及使用初体验

    RPC:Remote Procedure Call(远程服务调用) RPC是做什么的 通过RPC框架机器A某个进程可以通过网络调用机器B上的进程方法,就像在本地上调用一样. RPC可以基于HTTP或者 ...

  10. ofbiz最新版13.07.01环境搭建、安装(linux环境下)

    一.软件必备: 1.jdk1.7 2.mysql5.6 3.安装tomcat 二.安装: 1.安装 JDK1.7 2.安装mysql数据库 3.下载apache-ofbiz-13.07.01.zip ...