什么是單體模式
在面向?qū)ο缶幊讨刑尉龋覀冇袝r(shí)候需要只有一個(gè)對(duì)象或者實(shí)例,如注冊(cè)表业扒,線程池等检吆。俗話(huà)說(shuō)“一山不容二虎”,往往多個(gè)實(shí)例會(huì)導(dǎo)致軟件系統(tǒng)出錯(cuò)程储,或者導(dǎo)致資源浪費(fèi)蹭沛。這時(shí)候可以引入單體的設(shè)計(jì)模式,來(lái)限制產(chǎn)生新實(shí)例或?qū)ο蟆?/p>
單體模式(Singleton Pattern)就是確保某一個(gè)類(lèi)只有一個(gè)實(shí)例章鲤,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例摊灭。 ---《設(shè)計(jì)模式之禪》
java實(shí)現(xiàn)方式
- 定義私有訪問(wèn)權(quán)限的構(gòu)造函數(shù),避免被其他類(lèi)new出新對(duì)象
- 解決方法:
public calss Singleton {
private static Singleton firstInstance = null;
private Singleton(){}
public static Singleton getInstance(){
if(firstInstance == null) {
firstInstance = new Singleton();
}
}
return firstInstance;
}
可以從上面例子看出败徊,其他類(lèi)對(duì)這個(gè)類(lèi)的訪問(wèn)可以通過(guò)getInstance獲得同一個(gè)對(duì)象帚呼。
不過(guò),該方法在高并發(fā)條件下皱蹦,可能出現(xiàn)線程不安全的情況煤杀。可以利用synchronized關(guān)鍵字來(lái)消除這種問(wèn)題沪哺。這種解決方案也被稱(chēng)為懶漢式解決方法沈自。
- 餓漢式解決方法:
該解決方案直接在類(lèi)的內(nèi)部先實(shí)例化一個(gè)私有變量。而外部如果需要獲得該對(duì)象凤粗,必須通過(guò)getInstance方法來(lái)獲取酥泛。
public calss Singleton {
private static Singleton firstInstance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return firstInstance;
}
}
小擴(kuò)展:有上限的多例模式
要想實(shí)現(xiàn)能產(chǎn)生固定數(shù)量的實(shí)例類(lèi)今豆,可以采用以下方法:
public class Apple{
//最多產(chǎn)生三個(gè)蘋(píng)果實(shí)例
private static int maxNumOfApple = 3;
private static ArrayList<String> nameList = new ArrayList<String> ();
private static ArrayList<Apple> appleLisst = new ArrayList<Apple> ();
//當(dāng)前序列號(hào)
private static int countNumOfApple = 0;
static{
for(int i = 0; i < maxNumOfApple; i++){
appleList.add(new Apple('第'+ (i+1) + '個(gè)'));
}
}
private Apple(){};
private Apple(String name){
nameList.add(name);
}
//隨機(jī)獲得實(shí)例
public static Apple getInstance(){
Random random = new Random();
countNumOfApple = random.nextInt(maxNumOfApple);
return appleList.get(countNumOfApple);
}
}
javascript實(shí)現(xiàn)方式
- example1:
var Singleton = {
attribute: atr1,
attribute: atr2,
fun1 : function(){},
fun2 : function(){}
};
在這個(gè)例子中,可以通過(guò)Singleton這個(gè)對(duì)象訪問(wèn)所有的屬性和方法柔袁。但同時(shí)因?yàn)閖avascript對(duì)象的易變性呆躲,為了避免無(wú)意中改寫(xiě)變量,可以將單體對(duì)象中的代碼組織在命名空間中捶索。
在javascript中插掂,可以利用單體模式封裝某些專(zhuān)用的代碼,避免其他頁(yè)面的調(diào)用腥例。
var dom = (function (){
var _counter = 0;
var instance;
function generateId() {
return 'customId' + _counter++;
}
function create(tagName, id) {
var el = document.createElement(tagName);
el.id = id || generateId();
}
function createInstance() {
return {
generateId: generateId,
create: create
};
}
return {
getInstance: function() {
return instance || (instance = createInstance());
}
}
}(););
適用場(chǎng)景
- 要求生成唯一序列號(hào)的環(huán)境
- 整個(gè)項(xiàng)目需要一個(gè)共享訪問(wèn)點(diǎn)或共享數(shù)據(jù)
- 創(chuàng)建一個(gè)對(duì)象消耗資源過(guò)多