解读设计模式----单例模式(Singleton Pattern)

      单例模式可以保证一个类有且只有一个实例,并提供一个访问它的全局访问点.在程序设计中,有很多情况需要确保一个类只能有一个实例.从这句话可以看出,Singleton模式的核心:如何控制用户使用new对一个类的实例构造器的任意调用。如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?这应该是类设计者的责任,而不是使用者的责任。

 一、单例模式意图
      保证一个类有且只有一个实例,并提供一个访问它的全局访问点。

二、单例模式UML图(该图来至http://www.dofactory.com/)
     

三、示例解说单例模式
      看看下面这个简单的示例:

 1namespace DesignPattern.Singleton
 2{
 3    public class Singleton
 4    {
 5        //静态私有属性
 6        private static Singleton instance;
 7
 8        /// <summary>
 9        /// 私有构造器--让类的使用者调用不到此构造器
10        /// </summary>
11        private Singleton()
12        { }
13
14        public static Singleton Instance
15        {
16            get 
17            {
18                if (instance == null)
19                {
20                    instance = new Singleton();
21                }
22                return instance;  //返回的总是第一次实例的对象
23            }
24        }
25    }
26
27    //测试类
28    class TestSingleton
29    {
30        public static void Main2(string[] args)
31        {
32            Singleton t1 = Singleton.Instance;
33            Singleton t2 = Singleton.Instance;
34            Console.WriteLine(object.ReferenceEquals(t1, t2) == true);
35        }
36    }
37}

     提供一个静态的私有属性,并提供get来实现一个简单的单例.此外我们还可以通过静态只读属性来实现.看看下面这个MSDN上提供的示例:

 1/**//// <summary>
 2/// MSDN上Singleton模式的实现
 3/// </summary>

 4public class MsdnSingleton
 5{
 6   //声明的同时进行初始化
 7   public static readonly MsdnSingleton Instance = new MsdnSingleton();
 8        
 9   /**//// <summary>
10   /// 私有构造器
11   /// </summary>

12   private MsdnSingleton()
13   {
14   }

15}

      这样的单例实现的实质等同于提供一个静态的属性字段,通过静态构造器来初始化这个属性.因为要想访问静态字段,那静态构造器就首先执行,下面是代码示例:

 1public class SameSingleton
 2{
 3   //要想访问静态字段,那静态构造器就首先执行
 4   public static readonly SameSingleton Instance;
 5        
 6   /**//// <summary>
 7   /// 静态构造器-初始化Instance
 8   /// 静态构造器-完成静态字段(Instance)的初始化
 9   /// </summary>

10  static SameSingleton()
11  {
12      Instance = new SameSingleton();
13  }

14
15  /**//// <summary>
16  /// 私有构造器
17  /// </summary
18  private SameSingleton()

19  {
20 
21  }

22}

      上面的实现完全可以达到单例模式的意图,保证一个类仅且有一个实例,并提供一个全局访问点.而这在实际应用我们还得注意一点,就是在多线程的调用.于此,我们还得保证线程安全.要保证线程安全其实也是很简单就可以实现的,只需要通过加锁和双重判断就OK,下面是简单的多线程的线程安全的实现:

 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4
 5//多线程的Singleton模式实现
 6namespace DesignPattern.Singleton
 7{
 8    public class SingletonMultithread
 9    {
10        private static object lockHelper = new object();
11
12        private static volatile SingletonMultithread instane = null;
13        public static SingletonMultithread Instane
14        {
15            get 
16            {
17                if (instane == null)  //双检查
18                {
19                    lock (lockHelper)
20                    {
21                        if (instane == null)
22                        {
23                            instane = new SingletonMultithread();
24                        }

25                    }

26                }

27                return instane;
28            }

29        }

30        
31
32        //私有构造方法
33        private SingletonMultithread() 
34        {
35
36        }

37    }

38
39    class TestSingletonMultithread
40    {
41        public static void Main()
42        {
43            SingletonMultithread s1 = SingletonMultithread.Instane;
44            SingletonMultithread s2 = SingletonMultithread.Instane;
45            Console.WriteLine(object.ReferenceEquals(s1, s2) == true);
46        }

47    }

48}

49

其中:private static volatile Singleton instance=null;
--volatile:保证特定平台的实现必须不要去从新调整指令,保证对象构造的一个非常严格的顺序。

四、真实项目中的单例
      我曾经做过一个网球场的管理系统,客户要求使用C/S,(随便PS下客户,在我做需求的时候建议客户做B/S系统,管理和部署就很方便,也不用带上几百M的.NET Frameworks去装在客户电脑上了。可好心讨不了客户的笑颜,他硬说我是在给他做网页,还说他要的是软件不是网页,汗过........),在使用C/S做程序的时候我想大家都遇到过这样的情况,无论是通过按扭点击还是菜单来导航,通常我们是像下面这样实现的:

1private void ratingToolStripMenuItem_Click(object sender, EventArgs e)
2{
3    ratForm rat = new ratForm();
4    rat.MdiParent = this;
5    rat.Show();
6
7}

     我这里是使用的菜单控件,通过点击打开新窗体。如果是这样问题就出现了,每当我们点击一次菜单上的菜单项就会启动一个窗体,点几次就会启动几个窗体。见下图:


      这样显然是不符合要求的,我们应该做到让每个窗体只能Show一个出来,这时 单例模式 就能派上用场了。要保证外部不能创建类的实例,才单例中就是通过设置构造方法为私有private,所谓模式可说是一种设计套路,这里我们就依葫芦画瓢来画一次单例,设置构造方法私有,代码如下;

1private ratForm()
2{
3    InitializeComponent();
4}

      通过一个静态方法来对完成静态属性的初始化;

 1private static ratForm ratf = null;
 2public static ratForm GetInstance()
 3{
 4   if (ratf == null || ratf.IsDisposed)
 5   {
 6      ratf = new ratForm();
 7      ratf.MdiParent = mainForm.ActiveForm;
 8   }

 9   return ratf;
10}

     通过单例模式的引入,私有了构造方法,并通过一个静态的方法初始化静态字段,保证了类的唯一实例,方法GetInstance()就是单例的全局访问点。这样设计后就通过GetInstance()方法就得了这个窗体的唯一实例。

1private void ratingToolStripMenuItem_Click(object sender, EventArgs e)
2{
3    //ratForm rat = new ratForm();
4    //rat.MdiParent = this;
5    //rat.Show();
6    ratForm.GetInstance().Show();
7}

     通过单例模式的引入,改善了程序的设计,在窗体调用处只需要通过全局访问点这个静态方法就可以得到唯一的实例对象,然后调用其Show()方法,就达到了我们的要求。

五、使用单线程Singleton模式要点
--Singleton模式中的实例构造器可以设置为protected以也许子类派生。
--Singleton模式一般不要支持ICloneable接口,因为这可能导致对个对象实例,与Singleton的意图违背。
--Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的意图违背。
--Singleton模式只考虑到了对象创建的管理,没有考虑对销毁的管理。对于自带垃圾回收的平台可不考虑这点。

上面总结源于MSDN WebCast
---------------------------------------------------------------------------------------------------------

转载于:https://www.cnblogs.com/beniao/archive/2008/05/13/1145918.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463887.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站开发的小知识参考(慢慢收集备用)

inetinfo.exe占用80端口的解决方法 我在本机配置PHP环境时&#xff0c;安装的时候遇到80端口被占用&#xff0c;经过查询才知道&#xff0c;原来是Inetinfo.exe占用了80端口&#xff0c;于是把Inetinfo.exe服务关掉就可以正常安装PHP环境了。解决方法在windows服务管理里&#…

Linux下如何搭建Java环境

软件环境 虚拟机&#xff1a;VMware Workstation系统&#xff1a;Linux&#xff1a;CentOS-7-x86_64工具&#xff1a; 安装工具&#xff1a;SSH客户端搭建步骤 1&#xff1a;查询当前系统版本 cat /proc/version2&#xff1a;首先确认当前系统是否已经存在java环境 java -vers…

程序中提升几毫秒、节省几 kB 的内存有必要吗?

我记得我上小学的时候有一篇课文&#xff0c;说是有一个人很节省&#xff0c;不仅他自己家里节省&#xff0c;如果别人家吃饭乱扔的剩饭&#xff0c;他都会去收拾起来晒干存起来。然后刚好有一年饥荒&#xff0c;大家都没有米吃了&#xff0c;他就把他那些年存起来的米给大家吃…

pthread_join()函数理解

pthread_t tid; 使用方式&#xff1a;pthread_join(tid,NULL); 为什么要使用pthread_join()&#xff1f; 在很多情况下&#xff0c;主线程生成并起动了子线程&#xff0c;如果子线程里要进行大量的耗时的运算&#xff0c;主线程往往将于子线程之前结束&#xff0c; 但是如果主…

SmartTemplate学习入门一

php最简单的模板 Array的变量是由SmartTemplate内建函数assign&#xff08;&#xff09;来赋值的 具体语法如下 assign ( 模版中的变量, 要替换的内容 ) 或 assign ( Array内容 ) 和其他程序的变量一样&#xff0c;smartTemplate的变量是由特殊的{}所包含的。里面的内容可以是S…

人生感言

马云说的一些话&#xff0c;还是值得思考的&#xff1a; (1)、细节好的人格局一般比较差 (2)、态度比能力重要&#xff0c;选择同样也比能力重要 (3)、领导比员工多什么&#xff1f; 领导永远不要跟下属比技能&#xff0c;下属肯定比你强&#xff1b;如果不比你强&#x…

当MCU死机了,先把硬件抓过来~

关于软件开发中的偶发性问题&#xff0c;有些处理办法看似不是很难&#xff0c;但其实最重要的还是对问题的敏感度&#xff0c;而这份敏感度就来源于你对整个系统的理解和把握。当你能够尽快缩小问题代码的范围&#xff0c;在一定程度上就已经加快了解决问题的进度。之前我曾提…

青蛙学Linux—NFS

NFS&#xff0c;Network File Syttem&#xff0c;网络文件系统。它允许网络上运行不同操作系统的主机通过网络连接到运行NFS服务的主机上&#xff0c;以实现数据共享。NFS的配置非常简单&#xff0c;经过简单的设置既能快速使用NFS。 使用NFS&#xff0c;首先在服务端运行NFS服…

extjs 学习中

首先找了个js得开发工具&#xff1a;Komodo Edit 但是安装了好多次都没有出现提示&#xff0c;均告失败&#xff01;今天再次鼓起勇气安装试试&#xff1a;首先安装Komodo-Edit-4.3.2-1263; 成功&#xff01;然后&#xff1a; 下载extjs_api_catalogs-2.0.2-ko.xpi &#xff…

火眼睛睛查coredump(stl sort)------永远让比较函数对相同元素返回false

转载&#xff1a;http://blog.csdn.net/stpeace/article/details/51040218#cpp 看看如下代码的一个非常隐晦的错误&#xff0c; 虽然不会每次core dump, 但类似代码迟早会core dump&#xff0c; 好多人遇到过。 此问题极难定位&#xff0c; 看一下吧&#xff1a; [cpp] view pl…

P1648 看守

传送门 以二维的两个点\((x1,y1),(x2,y2)\)为例&#xff0c;那么他们之间的曼哈顿距离肯定为一下四个之一\((x1-x2)(y1-y2)\),\((x2-x1)(y1-y2)\),\((x1-x2)(y2-y1)\),\((x2-x1)(y2-y1)\)&#xff0c;而且为这四个里面最大的 然后搞一搞可以变成下面的样子\((x1y1)-(x2y2)\),\(…

好友让我看这段代码

周末的时候&#xff0c;一个微信好友让我旁边看一段代码在写下面的文章之前&#xff0c;我先简单说下写代码是一件非常有意思的事情&#xff0c;同时也是一件需要我们认真对待的事情&#xff0c;我不认为一定要把代码写的和大神一样看不明白&#xff0c;但是至少要逻辑清晰&…

使用github管理Eclipse分布式项目开发

使用github管理Eclipse分布式项目开发 老关我在前面的博文&#xff08;github管理iOS分布式项目开发&#xff09;中介绍了github管理iOS分布式开发&#xff0c;今天老关将向大家介绍使用github管 理Eclipse分布式项目。事实上我们的516inc团队这在开发一个多移动平台项目&#…

愉快且卓有成效:培养你与人相处的能力

毫无疑问&#xff0c;渊博的学识和不断的创新是事业成功的基础。然而&#xff0c;把一个概念变为成果&#xff0c;离开他人的合作&#xff0c;任何人&#xff0c;无论是伟人还是凡夫&#xff0c;都无法实现。与人合作得是否愉快且卓有成效&#xff0c;完全取决于你与人相处的能…

小玩一个并行多线程MCU—MC3172

大家好转发一篇杂烩君的文章&#xff0c;杂烩君是我同一个高中的老乡&#xff0c;他平时分享的嵌入式知识非常不错。——————大家好&#xff0c;我是杂烩君。最近&#xff0c;朋友送了块小板子&#xff0c;板子上的MCU是个很有意思的东西——并行多线程处理器MC3172 。通俗…

Android 人脸识别签到(一)

因为Android课程设计自己选题&#xff0c;所以作者选了这个相对简单的。本来开始是想做大学课程查签到&#xff0c;拍一张集体照&#xff0c;就可识别哪些人已到&#xff0c;哪些未到。查了一下百度AI开发平台的人脸识别接口&#xff0c;发现V3的接口文档有M:N的人脸识别&#…

[系列文章]上传文件管理控件v2

一、引言&#xff1a; 开发v1的时候&#xff0c;遇到很多困难&#xff08;因为我是新手&#xff09;&#xff0c;于是就上网找了一些资料。 其中&#xff0c;这篇《数据绑定的总结 》文章&#xff08;http://www.cnblogs.com/qingtianyzl/articles/351012.html&#xff09;被我…

[ mongoDB ] - mongoDB的基本操作

mongoDB的基本操作 强烈推荐参考官方用户手册&#xff1a; http://www.mongodb.org/display/DOCS 1)插入&#xff08;insert&#xff09; 插入的value是json对象&#xff0c;以下示例循环添加了10个用户信息&#xff0c;字段可以是字符串、数值、对象、数组等。 通过VUE查看&am…

STL中的multimap---顺便说说如何查找同一关键字对应的所有值

转载&#xff1a;http://blog.csdn.net/stpeace/article/details/44984639 我个人感觉哈&#xff0c; map的应用场景比multimap更多&#xff0c; 不过&#xff0c; 我们还是来学一下multimap。 我们知道&#xff0c; multimap中&#xff0c; 一个关键字可能对应多个不同的值&am…

信号量保护之位带操作

大家好&#xff0c;上篇文章写的一个中断操作变量的问题&#xff0c;鱼鹰帮忙回复了&#xff0c;大家可以再看看这篇文章。好友让我看这段代码CM3位带操作如果存储器系统支持“锁定传送”&#xff08; lockedtransfers&#xff09;&#xff0c;或者总线上只有一个主机&#xff…