设计模式学习笔记(二)——Singleton单件模式

转载 2007年09月18日 12:13:00
设计模式学习笔记(二)——Singleton单件模式

       这是我写模式设计的第二篇,首先来说说设计模式的分类。

       基本的23种设计模式从目的上可分为三种:

1、  创建型(Creational)模式:负责对象创建。

2、  结构型(Structural)模式:处理类与对象间的组合,可以解决一些继承依赖性的问题

3、  行为型(Behavioral)模式:类与对象交互中的职责分配,可以解决组件间如何和交互,隔离变化。

下面来说说单件模式:

首先说说单件模式产生的动机,也就是为什么会出现单件模式。有一些类在系统中只存在一个实例才能确保他们的逻辑正确性以及良好的效率。这时我想到我遇到的一个问题。我曾经遇到一个WinForm程序,运行后出现一个登陆框,输入用户名密码后点击登陆,然后显示一个登陆后的界面。但是点击登陆后,程序要做一些操作,由于这段操作用时相对较长,在不经意时,我有点击了一次登陆按钮,最后出现了两个对话框。如:我现在有两个Form窗体Form1Form2Form1上有一个按钮用来打开Form2并隐藏自己。我们可以这样写:

         private void button1_Click(object sender, System.EventArgs e)

        {

            Form2 form = new Form2();

            form.Show();

            this.Hide();

    }

如果我们在显示Form2前由一些比较耗时的操作。如:我们让线程的沉睡10秒在显示Form2,当我们在线程沉睡时继续点击Form1上的Button,有可能就会出现两个Form2的窗体。(我试过可以出现两个Form2,如果你有心试但没事出来别拿西红柿砍我,哈哈)

        private void button1_Click(object sender, System.EventArgs e)

        {

            Thread.Sleep(10000);

            Form2 form = new Form2();

            form.Show();

            this.Hide();

    }

这种情况出现不能怪客户多点了一下,也不能说是编译器不够智能,应该是我们程序上的Bug,我想这种情况用单件模式应该可以解决。

单件模式的使用意图就是:保证一个类仅有一个实例,并提供一个该实例全局的访问点(这句话当然不是我先说的,是引用Gof在《设计模式》中的一句话)

那类的设计者如何绕过常规的构造器来实现单件模式呢?下面就来谈谈单件模式的实现。

单件模式在结构上使用了景泰方法来约束构造器(也就是构造函数)创建对象。

在单线程的情况下:私有化构造函数,使类的使用者调用不到这个构造函数来new一个实例。类型中可以自己new一个实例。类中创建一个静态私有变量和Static公有属性。在公有属性中实现此类的实例化。这样在第一次请求时创建此对象。代码如下:

class Singleton

    {

        private static Singleton _instance;

       

        private Singleton(){}

 

        public static Singleton f_Instance

        {

            get

            {

                if(_instance == null)

                {

                    _instance = new Singleton();

                }

                return _instance;

            }

        }

    }

我在main函数中写入如下程序来查看一下这样写是否有效:

static void Main(string[] args)

        {

            Singleton t1 = Singleton.f_Instance;

            Singleton t2 = Singleton.f_Instance;

            Console.Write(object.ReferenceEquals(t1,t2));

            Console.Read();

        }

控制台显示为True,开来还是有效的。当然在Main中我也试过这样写:Singleton t1 = new Singleton(),编译时告诉我Singleton()不可访问(当然,人家是私有的,不是自家人当然不见)

这种单线程下的单件模式有几点要注意:

1、  构造器私有化(如果要此类被继承,可以用protected声明构造器)

2、  不要支持IClinieable接口,因为会导致多个对象实例的出现

3、  不能支持序列化

4、  单件模式只考虑了对象创建的管理,没有考虑对象的销毁管理(创建自己的对象,销毁的事交给垃圾回收器吧)

5、  不能应对多线程环境,因为会导致多个对象实例的出现

那在多线程下如何实现呢?代码如下:

class SingletonMuli//多线程Singleton模式

    {

        private static volatile SingletonMuli _instance;    //volatile是为了让编译器对此代码编译后的位置不进行调整

        private SingletonMuli(){}

        private static object lockHelper = new object();    //辅助器,不参与对象构建

        public static SingletonMuli f_Instance

        {

            get

            {

                if(_instance == null)

                {

                    lock(lockHelper)

                    {

                        if(_instance == null)       //双检查

                        {

                            _instance = new SingletonMuli();

                        }

                    }

                }

                return _instance;

            }

        }

    }

当然还有一些更简单的实现方法,如:

    class Singleton1//可以用在多线程环境

    {

        public static readonly Singleton1 _instance = new Singleton1();

        private Singleton1(){}

    }

其中要提到的是在_instance私有字段的实例化叫做“内联初始化”。内联初始化是指在声明时。

实际上面的代码上相当于如下代码:

Public static readonly Singleton1 _instance;

Static Singleton()  //静态构造函数

{

    _instance = new Singleton();        //私有构造器

}

Private Singleton(){}

内联初始化时会先执行静态构造器,如果没有静态构造函数,系统会默认一个。在访问此静态字段时执行静态构造器生成。静态构造器保证了在多线程时只有一个线程执行,自动加锁。

当然,第二种实现方式也有一些缺点,如:静态构造器必须是私有的、无参的。不过也可以用其他的方式解决这类问题。如可以用方法属性实现扩展或修改私有构造器。

现在我们可以回来看看我开始说的那两个Form的问题,我们现在可以这样实现:

        private static Form2 form;

 

        private void button1_Click(object sender, System.EventArgs e)

        {

            Thread.Sleep(10000);

            object lockhelp = new object();

            if(form == null)

            {

                lock(lockhelp)

                {

                    if(form == null)

                    {

                        form = new Form2();

                        form.Show();

                    }

                }

            }

            this.Hide();

        }

这样问题就解决了(我是没有点出来第二个Form2,如果那位点出来了,给我发Email,我请她/他在天津的烤鸭)

单件模式实际上是利用控制对象创造过程来控制对象的创造个数的方法,我们可以对其进行扩展,不是让他只生成一个对象,可以让他只生成几个对象,这样可以实现对象池。

单件模式的核心是:如何控制用户使用new对一个类的实例构造器的任意调用。 

相关文章推荐

【设计模式】学习笔记7:单件模式(Singleton)

走进单件模式 有些对象我们只需要一个,比如:线程池,缓存,对话框,处理偏好设置和注册表的对象,日志对象,充当打印机,显卡等设备的驱动程序对象等。 这些类的对象只能有一个实例,如果有多个,然而会导致许...

【读书笔记】HeadFirst设计模式——单件不简单:详述实现Singleton模式需要考虑的方方面面

(参考: 深入浅出单实例Singleton设计模式 ) 什么是单件? 单件就是保证一个类仅有一个实例,并提供一个访问它的全局访问点。——GOF 单件模式简单吗? 简单,的确简单,因为只...

《Head First 设计模式》学习笔记——单件(例)模式

《Head First 设计模式》学习笔记——单件(例)模式1.定义确保一个类只有一个实例,并提供一个全局访问点2.为什么需要单件模式?有一些对象我们只需要一个,如:线程池、缓存、对话框、注册表、日志...

《Head First 设计模式》学习笔记——单件模式

设计模式 单件模式:确保一个类只有一个实例,并提供一个全局访问点。 要点 单件模式确保程序中一个类最多只有一个实例。 在Java中实现单件模式需要私有的构造器、一个静态方法、一个静态变...

Head First 设计模式——单件模式(Singleton Pattern)

单件模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点 单件模式确保程序中一个类最多只有一个实例。我们在程序中会遇到这种情况如:线程池,缓存,对话框,...

设计模式读书笔记:Singleton(单件模式)

意图: 保证一个类仅有一个实例,并提供一个访问它的全局访问点 注意: 1.静态成员变量及静态成员方法 2.使用惰性初始化,它的返回值直到被第一次访问时才创建和保存 3.构造器是受保护的,试图直接实例化...

设计模式——单件模式(Singleton Pattern)

一、单件模式定义及经典实现 确保一个类只有一个实例,并提供一个全局访问点。 单例的经典(简单)实现如下:public class Singleton{ // 利用静态变量记录Singlet...

深入浅出设计模式(1)——单件模式(Singleton Pattern)

1          模式简介 singleton是设计模式家族中的小弟弟,重量轻,没有复杂的经历,很单纯,所以叫单件(just a joke)。因为简单,容易被人洞悉,所以经常被人唤来唤去,sin...

设计模式学习--单件模式(Singleton Pattern)

设计模式学习--单件模式 2013年6月6日 高考前一天 六六大顺 6月7、8号,录取吧!!! 设计模式继续学习,无聊的考试,让我少了很多学习的时间,下面学习所有模式当中最简单的单件模式,有的...

设计模式(二)单件模式Singleton(创建型)

SINGLETON(单件)—对象创建型模式        几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的。您希望在应用程序中共享数据库句柄,因为在...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)