创建型模式--单例模式(Singleton)

 Singleton:Ensure a class only has one instance, and provide a global point of access to it.

一个类只能有一个实例的创建模式。

一:引入

 在某些情况下一个类只能有一个实例,如果多于一个实例就会导致逻辑错误。

  • 非共享资源:如打印机,系统属性文件
  • 其他:如数据库主键生成器,只能有一个地方分配,否则会出现重复主键
  1. EagerSingleton(饿汉式单例):  
/** */ /**
 * 饿汉式单例
 
*/

public   class  EagerSingleton  ... {
    
//类加载时实例化
    private  static final EagerSingleton instance=new EagerSingleton();
    
//构造函数设为私有,不能以new的方式生成新的实例
    private EagerSingleton()
    
...{        
    }

    
//提供给客户的得到唯一实例的方法
    public static EagerSingleton getInstance()
    
...{
         
return instance;
    }

}
 

 

public   class  Client  ... {
      
public static void main(String args[])
      
...{
          EagerSingleton s1 
= EagerSingleton.getInstance();
          EagerSingleton s2 
= EagerSingleton.getInstance();

        
if( s1 == s2 )
          System.out.println( 
"s1 == s2" );
      }

}

问题:

  • 类在加载时就将自己实例化,对于象资源控制器之类的类初始化可能耗费很多时间。还可能会导致出现多线程首次同时引用子类的几率变得比较大。
  • 构造函数为私有,不能被继承。
  1. LazySingleton(懒汉式单例)--延迟加载(访问时加载)
/** */ /**
 * 懒汉式单例
 
*/
public   class  LazySingleton  ... {
    
//类加载时为null,不实例化
    private  static  LazySingleton instance=null;
    
//构造函数设为私有,不能以new的方式生成新的实例
    private LazySingleton()
    
...{        
    }

    
//提供给客户的得到唯一实例的方法
    public static LazySingleton getInstance()
    
...{
        
//如果没有创建实例就创建,否则就用以前创建了的那个。
        if (instance==null) instance=new LazySingleton();
         
return instance;
    }

}
  • 第一次访问时实例化,资源利用效率比饿汉式要好,但第一次访问时反应时间不如饿汉式。
  • 因为构造函数私有,也不能被继承。

上例没有考虑到多线程环境,如果第一个线程执行到 if(instance==null)且还没有执行instance=new LazySingleton()时,另一个线程也执行到 if(instance==null)这时条件也为true,所以也会执行new LazySingleton()导致多实例。

 

// 整个方法都加锁,防止多线程环境下的问题
     synchronized   public   static  LazySingleton getInstance()
    
... {
        
//如果没有创建实例就创建,否则就用以前创建了的那个。
        if (instance==null) instance=new LazySingleton();
         
return instance;
    }

 

/** */ /**
 * 懒汉式单例,多线程环境
 
*/

public   class  LazySingleton  ... {
    
// 类加载时为null,不实例化.
    
// volatile ensures that multiple threads handle the instance variable
    
// correctly
    
// when it is being initialized to the Singleton instance.
    private volatile static LazySingleton instance = null;

    
// 构造函数设为私有,不能以new的方式生成新的实例
    private LazySingleton() ...{
    }


    
// 两阶段加锁,防止多线程环境下的问题,效率比整个方法加锁高。
    public static LazySingleton getInstance() ...{
        
// 如果没有创建实例就创建,否则就用以前创建了的那个。
        if (instance == null...{
            
synchronized (LazySingleton.class...{
                
if (instance == null...{
                    instance 
= new LazySingleton();
                }

            }

        }

        
return instance;
    }

}

 

二:结构

    

三:实际应用

  1. java.lang.Runtime
public   class  Runtime  ... {
    
private static Runtime currentRuntime = new Runtime();

    
/** *//**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class <code>Runtime</code> are instance 
     * methods and must be invoked with respect to the current runtime object. 
     * 
     * 
@return  the <code>Runtime</code> object associated with the current
     *          Java application.
     
*/

    
public static Runtime getRuntime() ...
    
return currentRuntime;
    }


    
/** *//** Don't let anyone else instantiate this class */
    
private Runtime() ...{}
}

 

 

四:适用情形

Use the Singleton pattern when

there must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.

 

when the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying

参考文献:
1:阎宏,《Java与模式》,电子工业出版社
2:Eric Freeman & Elisabeth Freeman,《Head First Design Pattern》,O'REILLY

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值