Gof 定义

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

动机

保证在系统中只存在一个实例,这样才能保证逻辑的正确性和良好的效率。

单件模式单线程环境下实现

看下面一段代码:

public class Singleton
{private static Singleton _instance;//定义为私有,让类的使用者不能直接new一个该类的实例private Singleton() { }public static Singleton Instance{get{if (_instance == null){_instance = new Singleton();}return _instance;}}
}

上面的代码中将Singleton类的构造函数设置为私有,如果试图去用new去创建一个Singleton的实例,会出现编译错误

public class Test
{public static void Main(){//Singleton不可访问,因为他受保护级别限制Singleton t = new Singleton();}
}

要创建Singleton的实例我们可以像下面这样做

public class Test
{public static void Main(){Singleton t = Singleton.Instance;}
}

上面的代码完成了一个最简单的单例模式的实现,保证了实例的唯一性,如下的测试代码是可以顺利通过的

[TestMethod()]
public void Test()
{Singleton t1 = Singleton.Instance;Singleton t2 = Singleton.Instance;Assert.AreEqual(true, t1.Equals(t2));
}

单件模式多线程环境下实现

在多线程环境下上面代码仍然有可能得到Singleton类的多个对象实例,为什么在多线程环境下会可能创建出多个实例呢?看下面代码:

public class Singleton
{private static Singleton _instance;//定义为私有,让类的使用者不能直接new一个该类的实例private Singleton() { }public static Singleton Instance{get{//线程A执行到此进行if判断,会进入到if语句里面//在线程A执行_instance = new Singleton(); 前,线程B也到了if判断处,//此时_instance还没有被创建出来仍然为null,线程B也会进入到if语句中//这样线程A和线程B会各自构建一个Singleton的实例if (_instance == null){_instance = new Singleton();}return _instance;}}
}

所以上面的代码示例只能应用在单线程的环境下,如果需要实现在多线程环境下的单件模式就需要对上面的代码进行改进,如下

public class Singleton
{private static volatile Singleton _instance;//一个辅助性的对象private static object _lockHelper = new object();//定义为私有,让类的使用者不能直接new一个该类的实例private Singleton() { }public static Singleton Instance{get{if (_instance == null){lock (_lockHelper){if (_instance == null){_instance = new Singleton();}}}return _instance;}}
}

上面代码和前面的代码相比,在声明_instance时多了volatile关键字,添加了一个辅助对象
_lockHelper ,_lockHelper 其实没有什么实际的意义,仅供lock使用。
volatile在msdn中的解释如下
volatile 关键字表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值。

单件模式静态构造函数实现

上面分别说了单件模式在单线程和多线程的实现,下面介绍一种简单的方法,可以同时满足这两种,使用静态构造函数来实现。静态构造函数只在静态字段初始化之前初始化,就是说我们在访问访问静态字段会先访问静态构造函数。静态构造函数可以保证多线程中只有一个线程执行该静态构造函数,关于Net中静态构造函数机制可以参考CLR Via C# 学习笔记(5) 静态构造函数的性能

public class Singleton
{public static readonly Singleton _Instance = new Singleton();private Singleton() { }
}

上面的代码等同于

public class Singleton
{public static readonly Singleton _Instance;static Singleton(){_Instance = new Singleton();}private Singleton() { }
}

上面的方式虽然非常简单,但是不支持构造函数接受参数,因为在Net中静态构造函数不允许有参数。所以这种方式只适用于没有参数的情况下。而前面提到的单线程和多线程的那两种方式只要稍加改动就能支持传参,下面的代码是改进后的单线程下的单件模式,多线程和单线程类似

public class Singleton
{public static Singleton _instance;private Int32 _x;private Int32 _y;//私有构造函数中对_x _y 赋值private Singleton(Int32 x, Int32 y){_x = x;_y = y;}//此处不能使用属性了 ,因为有参数所以改成了一个静态方法public static Singleton GetInstance(Int32 x, Int32 y){if (_instance == null){_instance = new Singleton(x, y);}return _instance;}
}

不过在静态构造函数实现的方法中仍然可以通过一些其他的手段来达到参数的目的,如下:

public class Singleton
{public static readonly Singleton _Instance;static Singleton(){_Instance = new Singleton();}private Singleton() { }//添加属性,在调用的时候直接给属性赋值public Int32 X{get { return _x; }set { _x = value; }}public Int32 Y{get { return _y; }set { _y = value; }}private Int32 _x;private Int32 _y;
}

调用代码:

public class Test
{public static void Main(){Singleton t = Singleton._Instance ;t.X = 100;t.Y = 200;}
}

Singleton模式的几个要点:

  • Singleton模式中的实例构造器可以设置为protected以允许子类派生。
  • Singleton模式一般不要支持ICloneable接口,因为可能会导致多个对象实例。
  • Singleton模式一般不要支持序列化,因为也可能导致多个实例。
  • Singleton模式只考虑到对象创建的管理,没有考虑到对象销毁的管理,对支持垃圾回收的平台来讲,没有必要对销毁进行特殊的管理。

转载于:https://blog.51cto.com/oec2003/1045832

设计模式笔记(2)---单件模式(创建型)相关推荐

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

    Singleton单件(创建型模式) 动机(Motivation) 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性.以及良好的效率. 如何绕过常规的 ...

  2. 设计模式之工厂方法模式(创建型)

    一.模式定义 工厂方法模式:又称工厂模式,也叫虚拟构造器模式,属于构建型设计模式,工厂方法模式是在简单工厂模式上进行拓展,生产产品的过程由具体工厂类实现,基类只实现接口,这使得工厂方法模式可以在不修改 ...

  3. JavaScript设计模式读书笔记(一)= 创建型设计模式

    全系列目录 JavaScript设计模式读书笔记(一)=> 创建型设计模式 JavaScript设计模式读书笔记(二)=> 结构型设计模式 JavaScript设计模式读书笔记(三)=&g ...

  4. 23种设计模式介绍(一)---- 创建型模式

    由于设计模式篇幅比较大,如果在一篇文章讲完所有的设计模式的话不利于阅读.于是我把它分为三篇文章 23种设计模式介绍(一)---- 创建型模式 23种设计模式介绍(二)---- 结构型模式 23种设计模 ...

  5. iOS开发 - 面向对象设计的设计模式(一):创建型模式(附 Demo UML类图)

    继上一篇的面向对象设计的设计原则,本篇是面向对象设计系列的第二个部分:面向对象设计的设计模式的第一篇文章. 另外,本篇博客的代码和类图都保存在我的GitHub库中:中的Chapter2. 最开始说一下 ...

  6. 【设计模式】(八)--创建型模式--建造者模式

    [设计模式](八)–创建型模式–建造者模式 建造者模式 [设计模式](八)--创建型模式--建造者模式 建造者模式定义 构造者模式的优点 构造者模式的使用场景 构造者模式和工厂模式区别 构造者模式简单 ...

  7. 【设计模式_青春版】创建型|原型模式

    文章目录 原型模式(创建型) 原型模型的概念 一.实现Cloneable接口 二.实现自定义的顶层接口 java中的浅拷贝 Java中深拷贝 一.改造克隆方法 二.序列化与反序列化 总结 原型模式(创 ...

  8. 设计模式总结: 5种创建型,7种结构型,11种行为型

    设计模式总结: 5种创建型,7种结构型,11种行为型 (加粗的为常用模式) 5种创建型: 工厂方法模式factory 抽象工厂abstactfactory 单例模式singleton 建造者模式bui ...

  9. Prototype原型模式(创建型模式)

    1.原型模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只有一 ...

最新文章

  1. 爬虫之requests模块发送带header的请求
  2. Git 操作简单总结:廖雪峰教程
  3. Dubbo 3.0 前瞻之对接 Kubernetes 原生服务
  4. java file类包_Java中File类的常用API
  5. IIS 8.5配置.net网站[花了半个多小时]
  6. 2017年哪些网络安全威胁不容忽视?
  7. C++用Prim算法实现无向图最小生成树
  8. php服务器端注释,php标识和注释
  9. android 仿站小工具,仿站小工具下载
  10. 计算方法(三)分段线性插值和Hermite插值
  11. softice调试驱动程序
  12. 计算机学院学位证发放仪式,新征程,新梦想--计算机学院举办2019届毕业生学位授予仪式...
  13. The Little Schemer 中文版
  14. 你如何破解后安装PS cs6
  15. c/c++函数 -strtol strtoll strtoul strtoull 使用注意项cc
  16. 回归预测 | MATLAB实现PCR(主成分回归)多输入单输出
  17. LockSupport的park和unpark的原理
  18. 下载的视频太大无法放进u盘
  19. 中国珍珠养殖产业发展现状分析,淡水养殖仍然占据主导地位「图」
  20. Java设计模式 - 工厂模式

热门文章

  1. MSSQL 漏洞利用与提权
  2. 快速查看linux命令的用法----------TLDR
  3. 【搜索引擎Jediael开发笔记2】使用HttpClient下载网页至本地文件
  4. 切诺夫界证明(Chernoff bound)
  5. 微软欢迎所有热爱开源软件的朋友们来投稿![征稿开放时间:2015年8月17日]
  6. Log4j写入数据库详解
  7. 九种食物帮你赶走忧郁
  8. 还有人记得【日之韵】吗?——提供下载
  9. Ubuntu使用vi命令时,不能正常编辑文件,使用方向键时老是出现很多字母解决方案
  10. 阿里云短信验证解决方案(java版)(redis存储)