1. 程式人生 > >聊聊spring中的那些設計模式------單例模式

聊聊spring中的那些設計模式------單例模式

在這一年裡一直前進,卻忘記了總結,設計模式雖然在初入開發中並沒有明顯的體現,但是,如要在以後有更高層次的發展,設計模式是無可或缺的。這系列的文章是為了,將在學校中學習的設計模式與開發中常用的Spring結合起來,我就當大家都瞭解過Spring 的基本知識哈,讓初學者們在摸不著的設計模式中,可以切實體會到用處。

首先,讓我們從設計模式中最簡單的模式也很重要的開始,也就是我們的題目《單例模式》(Singleton Pattern)。單例模式,顧名思義是一種確保某一種類只有一個,而且自行例項化並想系統提供這個例項(也就是一個全域性都可以使用的物件),這種類被大家叫做單例類。單例模式是一種建立模式。一般的用途有以下幾個:

1、 當我們要求一個類只有一個例項時,可使用單例模式。(如池物件例如字串池。)

2、 當一個類需要頻繁例項化,卻又需要即時銷燬。(資源訪問物件)

像我們常用的ctrl+alt+del 呼叫的資源管理器,也是用了單例模式~(不信,你看看可不可以開啟兩個工作管理員~),哦,原來如此,總的來看,單例模式的主要是為了減少物件對系統資源的消耗。

單例模式的實現方法有兩種: 懶漢式和餓漢式。

1、 懶漢式也就是在系統剛開始載入的時候,不會生成這個單例物件,在第一次使用時,才會例項化生成,之後也都是這個。 

//懶漢單例模式

public class SingletonDemo {

    //先定義靜態變數,用以存放,生成的變數。定義為私有的是因為我們要讓使用者使用我們提供的公共方法去獲取這個例項而不是SingletonDemo.sld這樣簡單的拿到。

    private static SingletonDemo sld = null;



    //構造方法私有化,保證建立只能由類自己建立。。

    private SingletonDemo(){}

    //這個公共方法可以保證,物件的建立,只有一次,而且這有這個方法。用synchronize保證在多執行緒下,確保“第一次”是真的“第一次”(不要想多哈哈~)

    public static synchronized SingletonDemo getInstance(){

        if( sld == null){

           sld = new SingletonDemo();

        }

        return sld;

    }

}

100秒時間,仔細想想,以上的實現方法有什麼不好的?

1,2,3…100

好啦,時間到啦。

真聰明,沒錯,這個方法存在效率問題。仔細想想,我們給方法上鎖,在某一時間下,就可能只有一個執行緒去執行這個方法。此方法適合多執行緒不頻繁訪問,那我們換一種思路解決這個問題。

class SingletonDemo02{

    //先定義靜態變數,用以存放,生成的變數。定義為私有的是因為我們要讓使用者使用我們提供的公共方法去獲取這個例項而不是SingletonDemo.sld這樣簡單的拿到。

    private static SingletonDemo02 sld = null;



    //構造方法私有化,保證建立只能由類自己建立。

private SingletonDemo(){}



    // 我們將synchronize關鍵字不繫結在方法上,將他繫結在類上(由於類是唯一的,所以可以這樣做),

這種情況下,會比第一種效率上有所提高,因為在同一時間內,很多執行緒不會再方法上被阻塞了。

    public static  SingletonDemo02 getInstance(){

        if( sld == null){

            synchronized(SingletonDemo02.class){

                if(sld == null){

                    sld = new SingletonDemo02();

                }

            }

        }

        return sld;

    }

}

但是這樣還是會被阻塞(因為synchronized)在頻繁訪問的情況下,也會有不少的執行緒被阻塞。

我們來看看這樣。

//餓漢式單例

class SingletonDemo03{

private int[] array = new int[1024];

    //類載入時建立。

    private static final SingletonDemo03 sld = new SingletonDemo03();

    private SingletonDemo03(){}

    //這樣適合頻繁訪問

    public static  SingletonDemo03 getInstance(){

        return sld;

    }

private static getMore(){

….

}

}

這樣子建立物件。就屬於餓漢式了,在類載入時,就會建立物件。此方法適合頻繁訪問物件。

可是,這樣其實是不合理的,因為如果在SingletonDemo03類中,比如這個類很大,在我們需要呼叫這個類中的靜態getMore方法時,這個大物件,我們會不得不創建出來。這無疑會對效能有所優化。所以此方法只適合小物件頻繁呼叫

針對這種情況,我們借用Spring中延遲載入的策略來解決。

class SingletonDemo04{



    private SingletonDemo04(){}

    static class Lazy{//這個類會什麼時候會載入?

        public static final SingletonDemo04 slg = new SingletonDemo04();

    }

    public static SingletonDemo04 getInstance(){

        return Lazy.slg;

    }



    public static void getMore(){



    }



}

使用內部靜態類去實現延遲載入策略。這樣在訪問getMore方法時並不會載入物件。在切實的呼叫getInstance時,才會建立這個類物件。由此,我們知道了4種不同場景下的單例模式的實現。

以上是對單例模式的一些科普,接下來我們看看在Spring中是如何使用的單例模式的?

實際上在SpringIOC中每一個注入的Bean物件預設都是單例的。我們可以通過Bean標籤中的scope來實現單例模式。

具體就是這樣

<bean id="gll" class="...." scope="singleton" default-lazy-init="true"/>

這樣就可以得到延遲載入的單例物件,如果想要多例,可以把scope改為 prototype,這就是多例的。

在SpringBoot中可以使用@Scope("prototype")註解來實現多例。

如果喜歡的話,可以點個贊,有什麼疑問,可以在評論中說出來一起探討,我看到會回覆的~