记录点滴收获,汇聚知识乐园

脚步无法到达的地方,目光可以到达;目光无法到达的地方,梦想可以到达

导航

单例设计模式(李建忠老师)

singleton模式是所有设计模式当中最简单的一种模式,也是最基本的一种模式

在软件系统中,经常有这样一些特殊的类,必须保证它们在系统只只存在一个实例,才能确保它们的逻辑正确性,以及良好的效率,如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例,下面就此问题展开分析。

     有人可能会想:我只创建一个对象,然后告诉使用者你只能使用我创建的这个对象,你要是自己创建对象,你去死吧!!,我们要清楚一点,我们写的注释很少有人会去看(除了我们自己),所以如果你让别人去死,别人会活的很潇洒,因此我们不能用这种方式去保证系统的正确性,而是应该使其从语言上就做不到,这就是作为一个设计者的责任。

     好吧,既然不能用这种激进的方式去实现我们的要求,那我们就来从语法上去规范它,常规的类不论我们写不写构造器都不行,因为就算你不写构造器,编译器也会生成一个缺省的构造器。

所以首先我们需要将构造器禁用掉(这里的禁用指的是只有类内能够访问,类外无法访问),那好,既然构造器被禁用掉了,那么在外部我们无法使用关键字new来创建对象了,只能用一个方法来返回一个在类内生成的对象,接下来,如果我们把这个方法定义为实例方法,实例方法必须依靠一个对象才能调用,而构造器已经被禁用,客户端根本无法创建对象,因此此方法必须定义成静态方法,接下来我们通过私有构造器定义一个该类的对象(也就是客户端能访问到的唯一的对象),并将其赋值为空,接下来我们需要在我们定义的静态方法里给它赋值,大家知道,静态方法是无法访问实例成员的,因此我们需要将该变量定义为静态的,下面我们先贴出代码:

class Singleton

    {

        int x;

        int y;

        private Singleton()  //私有化构造器

        {

        }

        static Singleton instance = null;

 

        public static Singleton CreateSingleton()

        {

            if (instance == null)

            {

                instance = new Singleton();  //注意:这里由于instance为静态字段,因此其赋值需要调用静态构造器,但在这里我们并没有声明静态构造器,

                                                         //其实,当我们第一次使用静态字时,编译器会默认的帮我们生成一个静态构造器。这一点我们可以通过ildasm工具查看其IL代码证实。              

            }

            return instance;

        }

    }

    class Test

    {

        static void Main()

        {

            Singleton s1 = Singleton.CreateSingleton();

        }

    }

在CreateSingleton方法里,我们用了一个if 语句去判断对象是否是第一次被创建,如果是那就创建对象,如果不是,那就直接返回当前对象。

好了,我们似乎做到了,不仅保证了该类仅有一个实例,同时提供了一个该实例的全局访问点。

但是,事情并非我们想象的那么完美,这个设计模式仍然存在一些弊端,在实践编程的过程中,这个模式会发生多线程安全问题,我们来具体分析一下CreateSingleton这个方法,

假设线程1进入if语句,还未到达if语句的方法体中,此时实例对象instance仍然为空,此时控制权被线程2所掌握,进到if语句中进行判断,instance仍然为空,因此线程1和线程2将分别创建一个对象,这样的话系统里面会创建出两个对象。

此时就应该利用到静态构造器的线程安全来完成对象的创建,下面我贴出代码:

(这里我们采用的是内联初始化)

 public class Singleton

    {

        int x;

        int y;

 

     private Singleton() //构造器私有化

        {

        }

     public  static readonly  Singleton instance = new Singleton();//创建一个对象  ,这里调用的是静态构造器

    }

    public class Test

    {

       public  static void main()

        {

            Singleton s1 = Singleton.instance;        

        }

    }

在这里我们使用C#静态初始化机制实现了Singleton,且多线程安全。静态初始的过程中,对象的创建是同步的。

posted on 2011-10-14 17:15  guowenhui  阅读(1155)  评论(0编辑  收藏  举报