最简单的设计模式—Singleton

来源:互联网 发布:和男友逛街知乎 编辑:程序博客网 时间:2024/05/17 04:14
意图(intent):保证一个类仅有一个实例,并提供一个访问它的全局访问点。

适用性:

  • 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
  • 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

在软件系统中,经常有这样一些特殊的类,必须保证他们在系统中只存在一个实例,才能确保他们的逻辑正确性,以及良好的效率。比如说数据库访问,数据库的connection实例;再比如一个台式机的打印机也只能有一个实例。如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?这应该是类设计者的责任,而不是使用者的责任。

一个最简单的实现:

Class Singleton

{

       Private static Singleton single;

      

Private static Singleton(){}

 

       Public static Singleton getInstance()

{

       If(single == NULL)

              Return single = new Singleton();

       Else

              Return single;

}

}

在实现过程中,精髓就是把构造函数private掉。当然了,为了满足可以让子类扩展,也可以使构造函数为Protected。然后就是提供了一个公有、静态的函数用于得到这个实例,以及一个静态的成员变量。

上面说了,这是一个最简单的实现。如果考虑到多线程的话,那么上面的设计显然存在问题了。因为很有可能singletonnew了两遍,乃至n多遍。所以,一定要在new的地方进行加锁。

class Sm//多线程Singleton模式

{

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

private Sm(){}

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

public static Sm value

{

           get

        {

        if(_instance == null)

{

            lock(lockHelper)

            {

                if(_instance == null)       //double check

                {

                    _instance = new SingletonMuli();

                    }

                }

            }

            return _instance;

        }

}

}

 

当然还有一些更简单的实现方法,这里用到了一些c#的特性,如:

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

    {

        public static readonly Sm single = new Sm();

        private Sm(){}

    }

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

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

Public static readonly Sm single;

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

{

Single = new Sm();        //私有构造器

}

 

Private Sm(){}

内联初始化时会先执行静态构造器,如果没有静态构造函数,系统会默认一个。在访问此静态字段时执行静态构造器生成。静态构造器保证了在多线程时只有一个线程执行,自动加锁。当然,第二种实现方式也有一些缺点,如:静态构造器必须是私有的、无参的。不过也可以用其他的方式解决这类问题。如可以用方法属性实现扩展或修改私有构造器。

 

Singleton模式的扩展。既然可以让他只能生成一个实例,那么也就有办法让他生成n个实例。很简单的一种实现就是提供一个数组。构造函数一定是无参的吗?NO!我们也可以构造有参的,可以把参数通过getInstance(int a, int b, …),然后再通过它来交给构造函数。

 

 
原创粉丝点击