一起來學(xué)習(xí)設(shè)計(jì)模式:單例設(shè)計(jì)模式

前言:
單例設(shè)計(jì)模式也是非常常用的設(shè)計(jì)模式,比如我們所熟知的servlet他在Tomcat中是一個(gè)單例設(shè)計(jì)模式的實(shí)現(xiàn),那到底單例設(shè)計(jì)模式是什么,有什么用呢?咱們一起來學(xué)習(xí)

1.什么是單例設(shè)計(jì)模式

有些對象我們只需要一個(gè),比如配置文件,工具類,線程池,緩存,日志對象等等。如果我們創(chuàng)造多個(gè)實(shí)例會造成很多問題,比如占用資源過多,不一致的結(jié)果等。我們的單例設(shè)計(jì)模式就是保證實(shí)例只有一個(gè),就能很好地避免這些問題
單例設(shè)計(jì)模式有兩種:

  • 餓漢式
  • 懶漢式

2.餓漢式的實(shí)現(xiàn)

public class Singleton {
    //1.將構(gòu)造方法設(shè)為私有,不允許外部直接創(chuàng)建對象
    private Singleton(){

    }
    //2.創(chuàng)建一個(gè)實(shí)例
    private static Singleton instance = new Singleton();

    //3提供一個(gè)用于獲取實(shí)例的方法

    public static Singleton getInstance(){
        return instance;
    }
}

public class Test {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        //看是否指向同一個(gè)對象
        System.out.println(s1 == s2 ? "是同一個(gè)實(shí)例" :"不是同一個(gè)實(shí)例");
    }
}

image.png

從上面我們知道:
1.將構(gòu)造方法設(shè)為私有,不允許外部直接創(chuàng)建對象
2.創(chuàng)建一個(gè)靜態(tài)私有的實(shí)例
3.對外提供一個(gè)靜態(tài)的方法,返回這個(gè)實(shí)例
4.訪問的時(shí)候通過類名.靜態(tài)方法獲取
static修飾的是從類加載的時(shí)候就加載的,所以說當(dāng)Singleton類加載的時(shí)候就加載了這個(gè)實(shí)例;我們可以形象地把加載的這個(gè)過程稱為餓漢,因?yàn)樗I了,所以想快點(diǎn)吃到東西(從類加載的時(shí)候就加載進(jìn)來,迫不及待!imagine一下~)

3.懶漢式

public class Singleton2 {
    //將構(gòu)造方法私有化
    private Singleton2(){

    }
    //聲明類的唯一實(shí)例
    private static Singleton2 instance;
    //提供一個(gè)對外獲取實(shí)例的方法
    public static Singleton2 getSingleton2() {
        if(instance == null)
        instance = new Singleton2();
        return instance;
    }


}

public class Test {
    public static void main(String[] args) {
        //餓漢式
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        //看是否指向同一個(gè)對象
        System.out.println(s1 == s2 ? "是同一個(gè)實(shí)例" :"不是同一個(gè)實(shí)例");
        //懶漢式
        Singleton2 s3 = Singleton2.getInstance();
        Singleton2 s4 = Singleton2.getInstance();
        System.out.println(s3 == s4 ? "是同一個(gè)實(shí)例" :"不是同一個(gè)實(shí)例");
    }
}

image.png

從上面我們知道:
1.私有化構(gòu)造函數(shù)
2.聲明一個(gè)實(shí)例
3.提供對外的方法,當(dāng)?shù)谝粋€(gè)用戶訪問的時(shí)候就實(shí)例化instance對象,當(dāng)?shù)诙€(gè)再訪問的時(shí)候就不用再創(chuàng)建了,直接返回??雌饋硎遣皇呛軕校亢竺娴娜硕疾幌雱?chuàng)建了,都拜托第一個(gè)訪問的人了!!

4.兩者的區(qū)別

1.餓漢模式加載類的時(shí)候比較慢,但運(yùn)行的時(shí)候獲取對象的速度比較快,線程安全
2.懶漢模式加載類的時(shí)候比較快,但是在運(yùn)行時(shí)獲取對象的速度比較慢,因?yàn)槲覀兊谝淮卧L問的時(shí)候要創(chuàng)建對象,所以比較慢,同時(shí)懶漢模式線程是不安全的
3.為什么說餓漢模式的線程是安全的,懶漢模式線程是不安全的?舉個(gè)例子,現(xiàn)在有兩個(gè)線程thread1,thread2,他們都訪問了上述的兩種模式的對象,因?yàn)轲I漢模式在加載的時(shí)候就實(shí)例化了,所以取到的值只有唯一一個(gè),而懶漢模式,thread1有可能在if(instance == null)的時(shí)候還沒開始實(shí)例化,thread2也加進(jìn)來,這個(gè)時(shí)候就會有兩個(gè)對象
測試餓漢式

public class TestThread implements Runnable {
    
    @Override
    public void run() {
       // 測試餓漢式
        Singleton  s1 = Singleton.getInstance();
        System.out.println("對象被創(chuàng)建" + s1 + " 當(dāng)前線程" + Thread.currentThread().getName());
        System.out.println("hashCode" + s1.hashCode());
  
    }

    public static void main(String[] args) {

            TestThread t1 = new TestThread();
            TestThread t2 = new TestThread();
            new Thread(t1).start();
            new Thread(t2).start();

    }
}

image.png

測試懶漢式

public class TestThread implements Runnable {

    @Override
    public void run() {
       // 測試餓漢式
        Singleton2  s2 = Singleton2.getInstance();
        System.out.println("對象被創(chuàng)建" + s2 + " 當(dāng)前線程" + Thread.currentThread().getName());
        System.out.println("hashCode" + s2.hashCode());

    }

    public static void main(String[] args) {

            TestThread t1 = new TestThread();
            TestThread t2 = new TestThread();
            new Thread(t1).start();
            new Thread(t2).start();

    }
}

image.png

Look看到效果了吧!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡單、最易理解的設(shè)計(jì)模式,也因?yàn)樗暮啙嵰锥?,是?xiàng)目中最...
    成熱了閱讀 4,546評論 4 34
  • 1 單例模式的動機(jī) 對于一個(gè)軟件系統(tǒng)的某些類而言,我們無須創(chuàng)建多個(gè)實(shí)例。舉個(gè)大家都熟知的例子——Windows任務(wù)...
    justCode_閱讀 1,561評論 2 9
  • 1 場景問題# 1.1 讀取配置文件的內(nèi)容## 考慮這樣一個(gè)應(yīng)用,讀取配置文件的內(nèi)容。 很多應(yīng)用項(xiàng)目,都有與應(yīng)用相...
    七寸知架構(gòu)閱讀 6,981評論 12 68
  • 概念 確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化,并向整個(gè)系統(tǒng)提供一個(gè)訪問它的全局訪問點(diǎn),這個(gè)類稱為單例類。 特性 ...
    野狗子嗷嗷嗷閱讀 620評論 0 2
  • 今天坐上車離開家的時(shí)候,眼淚又滴滴答答的流了下來,我總是在離開地時(shí)候,把家里想的冷冷清清,想我走了,媽媽會難...
    叄新貳異閱讀 258評論 0 0

友情鏈接更多精彩內(nèi)容