天天看點

設計模式——單例模式

簡介

單例模式(Singleton Pattern)是Java中最簡單的設計模式之一。屬于建立型模式。該模式隻涉及到一個單一的類,負責建立自己的對象,并且隻有單個的對象被建立。這個類提供了一種通路其唯一的對象的方式,可以直接通路,不需要執行個體化該類的對象。

意圖

保證一個類有且隻有一個執行個體,并提供一個通路它的全局通路點。

主要解決

一個全局使用的類頻繁的建立于銷毀

如何解決

判斷系統是否有這個單利,如果有則傳回,如果沒有就建立

關鍵代碼

構造函數是私有的,然後公開一個GetInstance方法

圖示

設計模式——單例模式

應用執行個體

一個黨有且隻有一個主席

地球有且隻有一個,從有地球這個單例開始,所有的動物都用這個單例而且隻有這個單例可用

登入子產品、配置子產品

幾種實作方式

1. 懶漢式

1.1 懶漢式-線程不安全

public class Singleton{
    private static Singleton instance;
    //讓構造函數為 private,這樣該類就不會被執行個體化
    private Singleton(){}
    public static Singleton getInstance(){
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}      

1.2 懶漢式-線程安全

public class Singleton{
    private static Singleton instance;
    //讓構造函數為 private,這樣該類就不會被執行個體化
    private Singleton(){}
    public static synchronized Singleton getInstance(){
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}      

1.1 最大的問題是不支援多線程,1.2加上鎖synchonized就支援了多線程,嚴格意義上講1.1不是單例模式。

優點:第一次調用的時候才初始化,避免記憶體浪費

缺點:必須加鎖synchonized才能保證單例,但加鎖會影響效率

2. 餓漢式

public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}      

餓漢式多線程安全,比較常用,但容易産生垃圾對象

優點:沒有加鎖,執行效率會提高

缺點:類加載是就初始化,浪費記憶體

它基于 classloder 機制避免了多線程的同步問題,不過,instance 在類裝載時就執行個體化

3. 雙驗鎖/雙重校驗鎖

public class Singleton{
    private volatile static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}      

這種方式安全且在多線程的方式下保持高性能

執行個體

singleton.java

public class Singleton{
    private volatile static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}      

SingletonPatternDemo.java

public class SingletonPatternDemo {
    public static void main(String []args){
        Singleton object = Singleton.getInstance();
        Singleton object2 = Singleton.getInstance();
        System.out.println("End~~~~~~~~~~~");
    }
}      

推薦1:靜态内部類

public class Singleton1 {
    private static class MySingleton {
        public static final Singleton1 INSTANCE = new Singleton1();

    }
    private Singleton1() {
    }
    public static Singleton1 getInstance() {
        return MySingleton.INSTANCE;
    }      

由于靜态内部類MyS

ingleton

隻有在

getInstance()

方法第一次被調用時,才會被加載,而且構造函數為private,是以該種方式實作了懶漢式的單例模式。不僅如此,根據JVM本身機制,靜态内部類的加載已經實作了線程安全。

推薦2:枚舉

public interface MySingleton {
    void doSomething();
}

public enum Singleton implements MySingleton {
    INSTANCE {
        @Override
        public void doSomething() {
            System.out.println("complete singleton");
        }
    };

    public static MySingleton getInstance() {
        return Singleton.INSTANCE;
    }
}      
  • 枚舉類實作其實省略了

    private

    類型的構造函數
  • 枚舉類的域(field)其實是相應的enum類型的一個執行個體對象