1. 程式人生 > >建立型模式--單例模式(Singleton)

建立型模式--單例模式(Singleton)

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

一個類只能有一個例項的建立模式。

一:引入

 在某些情況下一個類只能有一個例項,如果多於一個例項就會導致邏輯錯誤。

  • 非共享資源:如印表機,系統屬性檔案
  • 其他:如資料庫主鍵生成器,只能有一個地方分配,否則會出現重複主鍵
  1. EagerSingleton(餓漢式單例):  
/**
 * 餓漢式單例
 
*/

publicclass EagerSingleton {
    
//類載入時例項化
privatestatic
final EagerSingleton instance=new EagerSingleton();
    
//建構函式設為私有,不能以new的方式生成新的例項
private EagerSingleton()
    
{        
    }

    
//提供給客戶的得到唯一例項的方法
publicstatic EagerSingleton getInstance()
    
{
         
return instance;
    }

}
publicclass Client {
      
publicstaticvoid main(String args[])
      
{
          EagerSingleton s1 
= EagerSingleton.getInstance();
          EagerSingleton s2 
= EagerSingleton.getInstance();

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

}

問題:

  • 類在載入時就將自己例項化,對於象資源控制器之類的類初始化可能耗費很多時間。還可能會導致出現多執行緒首次同時引用子類的機率變得比較大。
  • 建構函式為私有,不能被繼承。
  1. LazySingleton(懶漢式單例)--延遲載入(訪問時載入)
/** *//**
 * 懶漢式單例
 
*/

publicclass LazySingleton {
    
//類載入時為null,不例項化
privatestatic  LazySingleton instance=null;
    
//建構函式設為私有,不能以new的方式生成新的例項
private LazySingleton()
    
{        
    }

    
//提供給客戶的得到唯一例項的方法
publicstatic LazySingleton getInstance()
    
{
        
//如果沒有建立例項就建立,否則就用以前建立了的那個。
if (instance==null) instance=new LazySingleton();
         
return instance;
    }

}
  • 第一次訪問時例項化,資源利用效率比餓漢式要好,但第一次訪問時反應時間不如餓漢式。
  • 因為建構函式私有,也不能被繼承。

上例沒有考慮到多執行緒環境,如果第一個執行緒執行到 if(instance==null)且還沒有執行instance=new LazySingleton()時,另一個執行緒也執行到 if(instance==null)這時條件也為true,所以也會執行new LazySingleton()導致多例項。

//整個方法都加鎖,防止多執行緒環境下的問題
synchronizedpublicstatic LazySingleton getInstance()
    
{
        
//如果沒有建立例項就建立,否則就用以前建立了的那個。
if (instance==null) instance=new LazySingleton();
         
return instance;
    }
/**
 * 懶漢式單例,多執行緒環境
 
*/

publicclass LazySingleton {
    
// 類載入時為null,不例項化.
    
// volatile ensures that multiple threads handle the instance variable
    
// correctly
    
// when it is being initialized to the Singleton instance.
privatevolatilestatic LazySingleton instance =null;

    
// 建構函式設為私有,不能以new的方式生成新的例項
private LazySingleton() {
    }


    
// 兩階段加鎖,防止多執行緒環境下的問題,效率比整個方法加鎖高。
publicstatic LazySingleton getInstance() {
        
// 如果沒有建立例項就建立,否則就用以前建立了的那個。
if (instance ==null{
            
synchronized (LazySingleton.class{
                
if (instance ==null{
                    instance 
=new LazySingleton();
                }

            }

        }

        
return instance;
    }

}

二:結構

    

三:實際應用

  1. java.lang.Runtime
publicclass Runtime {
    
privatestatic 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.
     
*/

    
publicstatic 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