Android 應用最廣泛的模式——單例模式

● 單例模式介紹

單例模式是應用最廣的模式之一,也可能是很多初級工程師唯一會使用的設計模式。在應用這個模式時,代理對象的類必須保證只有一個實例存在。許多時候整個系統只需要擁有一個全局對象,這樣又利於我們協調系統整體的行爲。如在一個應用中,應該只有一個ImageLoader實例,這ImageLoader中又含有線程池、緩存系統、網絡請求等。很消化資源,因此,沒有理由讓它構造多個實例。這種不能自由構造對象的情況,就是單例模式的使用場景。

● 單例模式的定義

確保某一個類只有一個實例,而且自行實例化並像這個系統提供這個實例。

● 單例模式的使用場景

確保某個類有且只有一個對象的場景,避免產生多個對象消耗過多的資源,或者某種類型的對象只應該有且只有一個。例如,創建一個對象需要消耗的資源過多,如要訪問IO和數據庫等資源,這時就要考慮單例模式。

● 單例模式UML類圖

角色介紹:

(1)Client——高層客戶端;

(2)Singlet——單例類。

實現單例模式主要如下幾個關鍵點:

(1)構造函數不對外開放,一般爲Pirvate;

(2)通過一個靜態方法或者枚舉返回單例類對象;

(3)確保單例類的對象有且只有一個,尤其在多線程環境下;

(4)確保單例類對象在反序列化時不會重新構建對象。

通過見單例類的構造函數私有化,使得客戶端代碼不能通過new的形式手動構建單例類的對象。單例類會暴露一個公有的靜態方法,客戶端需要調用這個靜態方法獲取到單例類的唯一對象,在獲取這個單例對象的過程中需要確保線程安全,即在多線程環境下構造單例類的對象也是有且只有一個,這也是單例模式實現中比較困難的地方。

● 單例模式的簡單示例

單例模式是設計模式中比較簡單的,只有一個單例類,沒有其他的層次結構與抽象。該模式需要確保該類只能生成一個對象,通常是該類需要消耗較多的資源或者沒有多個實現的情況。例如一個公司只有一個CEO、一個應用只有一個Appliacton對象等。下面以公司裏的CEO爲例來簡單演示一下,一個公司可以有幾個VP、無數個員工,但是CEO只有一個,請看下面示例。

//普通員工
public class Staff {
	public void work() {
		//幹活
	}
}

//副總裁
public class VP extends Staff{
	@Override
	public void work() {
		//管理下面的經理
	}

}

//CEO,惡漢單例模式
public class CEO extends Staff{
	private static final CEO mCeo = new CEO();
	//構造函數私有
	private CEO() {
		
	}
	//公有的靜態函數,對外暴露獲取單例對象的接口
	public static CEO getCeo() {
		return mCeo;
	}
	@Override
	public void work() {
	//管理VP
	}
	

}

public class Company {
	private ArrayList<Staff> allStaffs = new ArrayList<>();
	public void addStaff(Staff per) {
		allStaffs.add(per);
	}
	public void showAllstffs() {
		for (Staff per : allStaffs) {
			System.out.println("obj : "+per.toString());
		}
	}

}

	public static void main(String[] args) {
		Company cp = new Company();
		Staff ceo1 = CEO.getCeo();
		Staff ce02 = CEO.getCeo();
		cp.addStaff(ceo1);
		cp.addStaff(ce02);
		//通過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.showAllstffs();
	}

輸出結果如下:

obj : text.CEO@7852e922
obj : text.CEO@7852e922
obj : text.VP@4e25154f
obj : text.VP@70dea4e
obj : text.Staff@5c647e05
obj : text.Staff@33909752
obj : text.Staff@55f96302

從上述代碼中可以看到,CEO類不能通過new的形式構建對象,只能通過CEO.getCEO()函數來獲取,而這個CEO對象是靜態對象,並且在聲明的時候就已經初始化,這就保證了CEO對象的唯一性。從輸出結果中發現,CEO兩次輸出的CEO對象都是一樣的,而VP、Staff等類型的對象都是不同的。這個實現的核心在於將CEO類的構造方法私有化,使得外部程序不能通過構造函數來構造CEO對象,而CEO類通過一個靜態方法返回一個靜態對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章