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