設計模式1——單例模式

weixin_33716557發表於2017-11-10

前記:本文主要是學習筆記,如有哪裡寫的不對,還希望大家指出,予以改正。
說起單例模式,現在網上百度一搜一大把,本文主要是參考拭心大神的文章,進行學習和總結。
接下來來說正事。

1、解釋

所謂的單例模式就是保證某個類只能被建立一次,而且以後在使用這個類的時候只能使用這個類物件。比如電腦上的工作管理員、Android中的application等。

2、作用

單例模式就是為了保證某個狀態一致性,在某個位置改變了該類物件的狀態,在其他地方使用的時候引用最新的狀態。

單例之-----懶漢模式
上程式碼:
public class TextActivity {
    TextActivity inStance = null;
    //防止通過構造器建立,將構造器改成私有的
    private TextActivity() {
    }

    public TextActivity getInstance() {
        if (inStance == null) {
            inStance = new TextActivity();
        }
        return inStance;
    }
}

注:
將構造器定義為私有的, 可以有效防止通過構造器建立物件。同時,這種方式雖然實現起來簡單,但是線上程上是不安全的,當多執行緒同時訪問時,由於執行緒的不確定性,可能會建立多個物件,在使用時產生混亂。

單例之-----懶漢模式的進化(加鎖控制的單例模式)

為了避免上述問題(執行緒不安全),可以在懶漢模式的基礎上增加同步鎖進行控制。但是如果只是簡單的鎖控制,在多執行緒訪問時,出現執行緒2需要線上程1訪問完才能訪問,執行緒3等待執行緒2......這樣一直等待太耗時間,所以就進一步優化,只有在該類物件沒有被建立的時候才進行鎖控制,有例項物件的時候直接返回該例項(上程式碼):

public class TextActivity {
    static TextActivity inStance = null;

    //防止通過構造器建立,將構造器改成私有的
    private TextActivity() {
    }

    public static TextActivity getInstance() {
        if (inStance == null) {
            createInstance();//使用同步鎖控制
        }
        return inStance;
    }

    //同步鎖控制
    public synchronized static void createInstance() {
        if (inStance == null) {
            inStance = new TextActivity();
        }
    }
}

注:
這種方式雖然保證了例項的唯一性,但是在多執行緒的情況下並沒有保證建立的先後順序。正常情況下,我們是在主執行緒中對類物件進行建立,其他執行緒訪問我們建立好的,這樣前面的問題就不存在了,如果要在多執行緒中訪問,就不安全,就要在類方法建立時進行初始化,而不是呼叫時才初始化。

單例之-----餓漢式單例

該模式使用了static的預先載入的特性
被static修飾的成員變數和成員方法獨立於該類的任何物件,也就是說它不依賴特定的例項,被類的所有例項共享,只要這個類被載入了,java虛擬機器就能根據類名在執行時資料區的方法區找到他們,因此static物件可以在它的任何物件建立之前訪問,無需引用任何物件。
這種方式基於classloader機制,避免了多執行緒的同步問題,在類載入的同時就已經建立了一個靜態的物件供系統使用,以後不會再改變,所以執行緒是安全的。在這種思路下就引發了新的單例模式的編寫方法:

上程式碼:
public class TextActivity {
    static TextActivity inStance = new TextActivity();

    //防止通過構造器建立,將構造器改成私有的
    private TextActivity() {
    }

    public static TextActivity getInstance() {
        return inStance;
    }
}

注:
這種方式有個缺點:不能從外部進行初始化,物件都是寫死的,但是很多大牛都推薦這樣寫。

總結

單例模式的編寫模式、方式多,但是可以根據實際情況選擇適合自己應用場景的,大部分情況下是不會在多執行緒中使用的,不過也不排除這種情況。假如我們使用前兩種方式,可以在主執行緒中建立例項,這樣在多執行緒引用時就已經存在了類物件,就不會出現上文中提到的問題。所以解決問題重要的是有思路,解決問題的方式不是一成不變的。

外篇:(一起共同學習進步)
QQ群:541144061

2961310-ede7f0337531e742.png
image.png

微信群:加我好友,寫好備註:android技術經驗分享

2961310-9bea62eaa2c237ad.png
image.png

相關文章