深入理解JavaScript系列(25):設(shè)計(jì)模式之單例模式詳解
來源:易賢網(wǎng) 閱讀:773 次 日期:2015-03-06 10:41:02
溫馨提示:易賢網(wǎng)小編為您整理了“深入理解JavaScript系列(25):設(shè)計(jì)模式之單例模式詳解”,方便廣大網(wǎng)友查閱!

這篇文章主要介紹了深入理解JavaScript系列(25):設(shè)計(jì)模式之單例模式詳解,本文給出了多種單例模式的實(shí)現(xiàn)方式,需要的朋友可以參考下

介紹

從本章開始,我們會逐步介紹在JavaScript里使用的各種設(shè)計(jì)模式實(shí)現(xiàn),在這里我不會過多地介紹模式本身的理論,而只會關(guān)注實(shí)現(xiàn)。OK,正式開始。

在傳統(tǒng)開發(fā)工程師眼里,單例就是保證一個(gè)類只有一個(gè)實(shí)例,實(shí)現(xiàn)的方法一般是先判斷實(shí)例存在與否,如果存在直接返回,如果不存在就創(chuàng)建了再返回,這就確保了一個(gè)類只有一個(gè)實(shí)例對象。在JavaScript里,單例作為一個(gè)命名空間提供者,從全局命名空間里提供一個(gè)唯一的訪問點(diǎn)來訪問該對象。

正文

在JavaScript里,實(shí)現(xiàn)單例的方式有很多種,其中最簡單的一個(gè)方式是使用對象字面量的方法,其字面量里可以包含大量的屬性和方法:

代碼如下:

var mySingleton = {

property1: "something",

property2: "something else",

method1: function () {

console.log('hello world');

}

};

如果以后要擴(kuò)展該對象,你可以添加自己的私有成員和方法,然后使用閉包在其內(nèi)部封裝這些變量和函數(shù)聲明。只暴露你想暴露的public成員和方法,樣例代碼如下:

代碼如下:

var mySingleton = function () {

/* 這里聲明私有變量和方法 */

var privateVariable = 'something private';

function showPrivate() {

console.log(privateVariable);

}

/* 公有變量和方法(可以訪問私有變量和方法) */

return {

publicMethod: function () {

showPrivate();

},

publicVar: 'the public can see this!'

};

};

var single = mySingleton();

single.publicMethod(); // 輸出 'something private'

console.log(single.publicVar); // 輸出 'the public can see this!'

上面的代碼很不錯(cuò)了,但如果我們想做到只有在使用的時(shí)候才初始化,那該如何做呢?為了節(jié)約資源的目的,我們可以另外一個(gè)構(gòu)造函數(shù)里來初始化這些代碼,如下:

代碼如下:

var Singleton = (function () {

var instantiated;

function init() {

/*這里定義單例代碼*/

return {

publicMethod: function () {

console.log('hello world');

},

publicProperty: 'test'

};

}

return {

getInstance: function () {

if (!instantiated) {

instantiated = init();

}

return instantiated;

}

};

})();

/*調(diào)用公有的方法來獲取實(shí)例:*/

Singleton.getInstance().publicMethod();

知道了單例如何實(shí)現(xiàn)了,但單例用在什么樣的場景比較好呢?其實(shí)單例一般是用在系統(tǒng)間各種模式的通信協(xié)調(diào)上,下面的代碼是一個(gè)單例的最佳實(shí)踐:

代碼如下:

var SingletonTester = (function () {

//參數(shù):傳遞給單例的一個(gè)參數(shù)集合

function Singleton(args) {

//設(shè)置args變量為接收的參數(shù)或者為空(如果沒有提供的話)

var args = args || {};

//設(shè)置name參數(shù)

this.name = 'SingletonTester';

//設(shè)置pointX的值

this.pointX = args.pointX || 6; //從接收的參數(shù)里獲取,或者設(shè)置為默認(rèn)值

//設(shè)置pointY的值

this.pointY = args.pointY || 10;

}

//實(shí)例容器

var instance;

var _static = {

name: 'SingletonTester',

//獲取實(shí)例的方法

//返回Singleton的實(shí)例

getInstance: function (args) {

if (instance === undefined) {

instance = new Singleton(args);

}

return instance;

}

};

return _static;

})();

var singletonTest = SingletonTester.getInstance({ pointX: 5 });

console.log(singletonTest.pointX); // 輸出 5

其它實(shí)現(xiàn)方式

方法1:

代碼如下:

function Universe() {

// 判斷是否存在實(shí)例

if (typeof Universe.instance === 'object') {

return Universe.instance;

}

// 其它內(nèi)容

this.start_time = 0;

this.bang = "Big";

// 緩存

Universe.instance = this;

// 隱式返回this

}

// 測試

var uni = new Universe();

var uni2 = new Universe();

console.log(uni === uni2); // true

方法2:

代碼如下:

function Universe() {

// 緩存的實(shí)例

var instance = this;

// 其它內(nèi)容

this.start_time = 0;

this.bang = "Big";

// 重寫構(gòu)造函數(shù)

Universe = function () {

return instance;

};

}

// 測試

var uni = new Universe();

var uni2 = new Universe();

uni.bang = "123";

console.log(uni === uni2); // true

console.log(uni2.bang); // 123

方法3:

代碼如下:

function Universe() {

// 緩存實(shí)例

var instance;

// 重新構(gòu)造函數(shù)

Universe = function Universe() {

return instance;

};

// 后期處理原型屬性

Universe.prototype = this;

// 實(shí)例

instance = new Universe();

// 重設(shè)構(gòu)造函數(shù)指針

instance.constructor = Universe;

// 其它功能

instance.start_time = 0;

instance.bang = "Big";

return instance;

}

// 測試

var uni = new Universe();

var uni2 = new Universe();

console.log(uni === uni2); // true

// 添加原型屬性

Universe.prototype.nothing = true;

var uni = new Universe();

Universe.prototype.everything = true;

var uni2 = new Universe();

console.log(uni.nothing); // true

console.log(uni2.nothing); // true

console.log(uni.everything); // true

console.log(uni2.everything); // true

console.log(uni.constructor === Universe); // true

方式4:

代碼如下:

var Universe;

(function () {

var instance;

Universe = function Universe() {

if (instance) {

return instance;

}

instance = this;

// 其它內(nèi)容

this.start_time = 0;

this.bang = "Big";

};

} ());

//測試代碼

var a = new Universe();

var b = new Universe();

alert(a === b); // true

a.bang = "123";

alert(b.bang); // 123

更多信息請查看IT技術(shù)專欄

更多信息請查看腳本欄目
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)