1. 程式人生 > >Android 單例模式

Android 單例模式

文章目錄

1、單例模式介紹

據說在一個app 中,單例物件的類必須保證只有一個例項存在,系統只有一個全域性變數存在。

2、單例模式的簡單例子

假設一個公司在 只能有一個CEO ,可以有多個經理,員工。那麼我們就把CEO 設為單例模式,並且在不同位置例項化,看看是不是一個例項。

package com.example.menglux.simplesingle;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Company cp = new Company();

        //CEO 物件只能通過getCeo 函式獲取
        Staff ceo1 = CEO.getCeo();
        Staff ceo2 = CEO.getCeo();

        //新增 CEO 例項進列表
        cp.addStaff(ceo1);
        cp.addStaff(ceo2);

        //通過 new 建立 VP 物件
        Staff VP1 = new VP();
        Staff VP2 = new VP();

        //通過new 建立Staff 物件
        Staff Staff1 = new Staff();
        Staff  Staff2 = new Staff();
        Staff Staff3 = new Staff();



        //新增 經理 員工 例項物件 進列表
        cp.addStaff(VP1);
        cp.addStaff(VP2);
        cp.addStaff(Staff1);
        cp.addStaff(Staff2);
        cp.addStaff(Staff3);


        //顯示列表裡面的類
        cp.showAllStaffs();
    }

    //公S司類
    public class Company {
        private List<Staff> allStaffs = new ArrayList<Staff>();    //建立一個列表,用來儲存,類

        public void addStaff(Staff per) {     //向列表添類 例項化物件
            allStaffs.add(per);
        }

        public void showAllStaffs() {      //將列表的類都顯示出來
            for (Staff per : allStaffs) {
                System.out.println("Obj: " + per.toString());
            }
        }
    }



    //普通員工的類
    public static class Staff {
        public void work(){
            //do something
        }
    }


    //經理的類
    public class VP extends  Staff {
        @Override
        public void work(){
            //do something
        }
    }



    //CEO 的 類
    public static class CEO extends  Staff {
        private static final  CEO mceo = new CEO(); //引用私有構造方法

        private CEO () {

        }

        public static  CEO getCeo () {
            return mceo;
        }

        @Override
        public void work(){
            //do something
        }
    }
}

我們執行一下 可以看到答應你出來的log:

09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: [email protected]
09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: [email protected]


09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: [email protected]
09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: [email protected] 09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: [email protected] 09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: [email protected] 09-20 13:47:01.039 8961-8961/com.example.menglux.simplesingle I/System.out: Obj: [email protected]

其中新增的兩個 CEO 例項是兩個一樣的資料。也就是說兩個例項是同一個。

上面程式碼我們可以知道,CEO 類不能通過 new 的形式來構造物件,只能通過 CEO.getCeo() 的函式來獲取,而這個CEO 物件是靜態物件,並且在宣告的時候已經初始化,這就保證了
CEO 物件的唯一性。

3、懶漢模式實現單例模式

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

getInstance() 方法裡添加了synchronized 關鍵字,也就是 getInstance 是一個同步方法,這就保證多執行緒情況下單例的唯一性。
優點:單例只有在使用時才被例項化
缺點:每次呼叫 getInstance 都進行同步,造成不必要的同步開銷。

4、Double Check Lock (DLC) 實現單例

    public static class Singleton {
        private static Singleton sinstance;

        private Singleton() {
        }

        public void doSomething() {
            //dosomething
        }

        private static Singleton getInstance() {
            if (sinstance == null) {
                synchronized (Singleton.class) {
                    if (sinstance == null) {
                        sinstance = new Singleton();
                    }
                }
            }
            return sinstance;
        }
    }

優點:資源利用率高
缺點:第一次載入慢,在高併發的狀態下會出現小概率 缺陷

5、靜態內部類單例模式

 public static class Singletion {
        private Singletion() {
            
        }
        
        public  static Singleton getInstance() {
            return SingletonHolder.sInstance;
        }
        
        
        /*靜態內部類*/
        private static class SingletonHolder {
            private static final Singleton sInstance = new Singleton();
        }
    }

1)第一次載入Singletion 類時不會初始化sInstance,只有在第一次呼叫Singleton的 getInstance方法時才會導致sInstance被初始化。
2)不僅保障執行緒安全,而且還是能夠保證單例物件的唯一性。

6、列舉單例

    public enum SingletonEnum {
        INSTANCE;
        public void doSomething() {
            //dosomething
        }
    }

1)寫法簡單
2)系統預設 執行緒安全

具體怎麼使用 沒深入研究

7、使用容器是實現單例模式

這裡只是把 建立的單一的實體類物件,放到hash 表裡面。

    public static class SingletonManager {
        private static Map<String, Object> objMap = new HashMap<String, Object>();
        
        private SingletonManager() {}
        
        public static void registerService(String key, Object instance) {
            if (!objMap.containsKey(key)) {
                objMap.put(key,instance);
            }
        }
        
        public static Object getService (String key) {
            return objMap.get(key);
        }
    }

文獻參考:
Android 原始碼設計模式解析與實戰 第二版

本人鄭重宣告,本部落格所編文章、圖片版權歸權利人持有,本博只做學習交流分享所用,不做任何商業用途。訪問者可將本博提供的內容或服務用於個人學習、研究或欣賞,不得用於商業使用。同時,訪問者應遵守著作權法及其他相關法律的規定,不得侵犯相關權利人的合法權利;如果用於商業用途,須徵得相關權利人的書面授權。若文章、圖片的原作者不願意在此展示內容,請及時通知在下,將及時予以刪除。