设计模式思考之单件模式

2019-03-03  本文已影响0人  lhsjohn

单件模式的定义

确保一个类只有一个实例,并提供一个全局访问点。

类图

单件模式.jpg

1.其中uniqueInstance 变量持有唯一的单间实例

2.getInstance()方法是静态的,这意味着它是一个类方法,所以可以在代码的任何地方使用Singleton.getnstance()访问它。这样和访问全局变量一样,只是多了一个优点:单件可以延迟实例化。

3.单件模式的类也可以是一般的类,具有一般的数据和方法。

下面是一个单件模式的经典实现:

Public class Singleton(){
//利用一个静态变量来记录Singleton类的唯一实例
Private static Singleton uniqueInstance;
//这里是用到的其他的有用的实例化的变量

//把构造器类设置为私有的,只有自Singleton类内才可以调用构造器
Private Singleton() { }
 
//用getInstance()方法实例化对象,并返回这个对象的实例
 Public static Singleton getInstance(){
    If(uniqueInstance==null) {  
       uniqueInstance=new Singleton();
 }
     Return uniqueInstance;
 
}

//这里是其他有用的方法

}

单件模式的多线程之伤

现在我们知道,绝大多数的应用程序都是多线程的,那么我们如果采用上面经典的单例模式的实现化,遇到多线程情况,就会遇到很大的麻烦了

下面我们来处理这种麻烦,处理多线程

在这里只需要我们把getInstance() 变成同步(synchronized)方法即可。


Public class Singleton(){
//利用一个静态变量来记录Singleton类的唯一实例
 Private static Singleton uniqueInstance;
//这里是用到的其他的有用的实例化的变量

 //把构造器类设置为私有的,只有自Singleton类内才可以调用构造器
Private Singleton() { }
 
//用getInstance()方法实例化对象,并返回这个对象的实例
Public static synchronized Singleton getInstance(){
    if(uniqueInstance==null) {  
     uniqueInstance=new Singleton();
}
   Return uniqueInstance;
 
 }

//这里是其他有用的方法

}


通过增加synchronized 关键字到getInstance()方法中,我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。

但这里需要我们注意的是,尽管用这个方式可以很简单的解决了上面的问题,但是这种方法却会降低应用程序的性能。

所以我们考虑一下,能否改善多线程呢?

下面是我们可以采取的几种选择:

1.如果getInstance()的性能对于应用程序不是很关键,就什么也不用去做,直接可以采取上面所说的加上 synchronized 的做法。

2.使用”急切”创建实例,而不用延迟实例化的方法

 Public class Singleton{
 //在静态初始化器中创建单件,这段代码保证了线程安全。
Private static Singleton uniqueInstace= new     Singleton();
  
Private Singleton () {}

Public static Singleton getInstance() {
        Return uniqueInstance;
     }

 }


采用这个做法,我们依赖JVM 在加载这个类时马上创建此唯一的单件实例。JVM保证在任何线程访问uniqueInstance静态变量之前,一定会创建此实例。

3.用“双重检查加锁”,在getInstance()中减少同步
利用双重检查加锁,首先检查是否实例已经创建了,如果尚未创建,”才”进行同步,这样一来,只有第一次会同步,这正是我们想要的。


 Public class Singleton{
 //在静态初始化器中创建单件,这段代码保证了线程安全。
Private static Singleton uniqueInstace;
  
Private Singleton () {}

Public static Singleton getInstance() {
 If(uniqueInstance ==null){
   Synchronized(Singleton.class) {
    If(uniqueInstance ==null){
     uniqueInstance =new Singleton();
   }
  }
 }
    Return uniqueInstance;
 }
}

注意如果使用的是JVM1.2或之前的版本,我们必须建立单间注册表,以免垃圾回收器将单件回收。

总的来说,单件模式相对于其他模式来说类图结构虽然没有那么复杂,但它却扮演着非常重要的角色,在保证应用程序的稳定性和安全性方面起着非常重要的作用。

作者:lhsjohn

上一篇 下一篇

猜你喜欢

热点阅读