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. 关于Content-Type: multipart/form-data的支持

    关于Content-Type: multipart/form-data的支持  发布于 537天前  作者 yzhang226  303 次浏览  复制  上一个帖子  下一个帖子  标签: 无 今天 ...

  2. 2017.9.16 Web 应用开发环境搭建与开发工具安装

    1.JDK的下载与安装 1.1 在网址:http://javase/downloads/index.jsp网站下载最新的JDK版本 1.2 安装jdk,双击下载好的.exe文件运行,一般默认安装在c盘 ...

  3. 2017.10.21 Java中的数据源与连接池技术

    1.数据源技术就是预先建立好一定的数量的数据库连接,并将这些连接保存在连接池中,有连接池负责对这些数据库连接管理,当访问数据库时,只需要从连接池中取出有空闲状态的数据库连接:当程序访问数据库结束时,释 ...

  4. 2017.9.25 JSP内置对象的概述

    1.JSP的定义: 在JSP中是为了便于数据信息的存储.传递.获取,专门设置了九个内置对象, jsp内置对象是指他们是预先设定的,不需创建,每个对象都有自己的属性和方法. 2.JSP内置对象 对象名称 ...

  5. Vue路由讲解

    1>router-link和router-view组件 2>路由配置 a.动态路由 import Home from "@/views/Home.vue"; expor ...

  6. web之HTTP协议

    1.web引用程序 web(world wide web)也叫万维网,是一种基于超文本和HTTP的.全球性的.动态交互的.跨平台的分布式图形信息系统.是建立在Internet上的一种网络服务,为浏览者 ...

  7. 微信小程序开发:禁止输入表情的控制,验证方法,光标控制

    <input class="weui-input" name="receiptMan" maxlength="10" bindinpu ...

  8. JSP自定义标记

    JSP自定义标记(可以使JSP网页变得简洁并且易于维护) 一.自定义标记的方式 1.实现接口Tag 2.继承类TagSupport或BodyTagSupport   二.JSP自定义标记的生命周期 1 ...

  9. javaWeb css图文混排

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

  10. iOS第三方支付(支付宝)

    使用支付宝进行一个完整的支付功能,大致有以下步骤: 与支付宝签约,获得商户ID(partner)和账号ID(seller) 下载相应的公钥私钥文件(加密签名用) 下载支付宝SDK 生成订单信息 调用支 ...