設計模式(單例模式)

1、簡介

單例模式是設計模式中使用最廣泛的一種設計模式,它是對象建立模式,用於產生一個對象的具體實例,
 確保系統中一個類只有一個實例。html

2、使用場景及優勢

對於頻繁使用的對象,能夠省略建立對象花費的時間。同時因爲new操做的吃書減小,所以對系統內存
的使用頻率會下降,減輕了GC壓力,縮短了GC停頓時間。java

3、常見表現形式

1.在類加載時初始化單例屬性(優勢:效率較高,多線程安全;缺點:增多程序加載時的額外負載)設計模式

public class ServiceConnation1
{
    /**
     * 類加載時就實例化單例屬性,此策略較爲安全,多線程時不會產生多個實例。可是當被實例化的
     * 類的構造方法須要作大量工做、或作者遠程鏈接操做就會使得程序在啓動時耗去很長的時間,致
     * 使啓動時間延長,用戶體驗下降。
     */
    private static ServiceConnation1 sc = new ServiceConnation1();
    
    private InitialContext context;
    
    private ServiceConnation1()
    {
        try
        {
            /**
             * 此處並無指定properties屬性,只是示例簡要的結構,模擬遠程鏈接操做等
             * 較爲耗時的初始化代碼,程序並不能運行成功。
             */
            context = new InitialContext();
        }
        catch (NamingException e)
        {
            e.printStackTrace();
        }
    }
    
    public static ServiceConnation1 getInstance()
    {
        return sc;
    }
    
    public Object getService(String name) throws NamingException
    {
        
        return context.lookup(name);
    }
}

2.延遲加載策略(優勢:減小程序加載時的負載;缺點:須要引入同步,效率低下)安全

 

public class ServiceConnation2
{
    
    private static ServiceConnation2 sc = null;
    
    private InitialContext context;
    
    private ServiceConnation2()
    {
        try
        {
            /**
             * 此處並無指定properties屬性,只是示例簡要的結構,模擬遠程鏈接操做等
             * 較爲耗時的初始化代碼,程序並不能運行成功。
             */
            context = new InitialContext();
        }
        catch (NamingException e)
        {
            e.printStackTrace();
        }
    }
    
    public static synchronized ServiceConnation2 getInstance()
    {
        /**
         * 在調用方法是判斷是否初始化單例對象,這樣能夠很好的解決上述啓動耗時的問題,方法在不添
         * 加同步關鍵字的時候,在非多線程運行下較爲可靠,效率也較高。可是在多線程的狀況下可能會
         * 產生多個實例,所以須要給方法添加synchronized修飾,這樣效率也大大下降了。
         */
        if(sc == null){
            sc = new ServiceConnation2();
        }
        return sc;
    }
    
    public Object getService(String name) throws NamingException
    {
        
        return context.lookup(name);
    }
}

3.內部類延遲加載策略(改進前兩種的缺點,推薦使用)多線程

public class ServiceConnation3
{
    
    private InitialContext context;
    
    private ServiceConnation3()
    {
        try
        {
            /**
             * 此處並無指定properties屬性,只是示例簡要的結構,模擬遠程鏈接操做等
             * 較爲耗時的初始化代碼,程序並不能運行成功。
             */
            context = new InitialContext();
        }
        catch (NamingException e)
        {
            e.printStackTrace();
        }
    }
    
    public static ServiceConnation3 getInstance()
    {
        /**
         * 爲了解決因延長加載而帶來的同步效率低下的問題,將程序改進爲內部類的方式實例化單例對象
         */
        return ServiceConnationHolder.sc;
    }
    
    public Object getService(String name) throws NamingException
    {
        return context.lookup(name);
    }
    
    /**
     * ServiceConnationHolder爲內部類,在程序初始化的收不會被加載,所以利用內部類的
     * 這種特性能夠實現延遲加載,同時又不存在多線程安全帶的問題。
     */
    private static class ServiceConnationHolder
    {
        private static ServiceConnation3 sc = new ServiceConnation3();
    }
}

 

4、測試

public class ServiceConnation
{
    
    private ServiceConnation()
    {
        try
        {
            System.out.println("************do inital something************");
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    
    public static ServiceConnation getInstance()
    {
        return ServiceConnationHolder.instance;
    }
    
    public Object getService(String name) throws NamingException
    {
        System.out.println("************getService************");
        return new Object();
    }
    
    private static class ServiceConnationHolder{
        public static ServiceConnation instance = new ServiceConnation();
    }
}

 

public class SingletonTest
{
    @Test
    public void testInitalSingleton(){
        ServiceConnation sc = ServiceConnation.getInstance();
        try
        {
            sc.getService("beanName1");
            sc = ServiceConnation.getInstance();
            sc.getService("beanName2");
        }
        catch (NamingException e)
        {
            e.printStackTrace();
        }
    }
}
相關文章
相關標籤/搜索