在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 設(shè)計(jì)模式之單例模式
代碼復(fù)用模式(避免篇)
S.O.L.I.D 五大原則之接口隔離原則 ISP
設(shè)計(jì)模式之狀態(tài)模式
JavaScript 核心(晉級高手必讀篇)
設(shè)計(jì)模式之建造者模式
JavaScript 與 DOM(上)——也適用于新手
設(shè)計(jì)模式之中介者模式
設(shè)計(jì)模式之裝飾者模式
設(shè)計(jì)模式之模板方法
設(shè)計(jì)模式之外觀模式
強(qiáng)大的原型和原型鏈
設(shè)計(jì)模式之構(gòu)造函數(shù)模式
揭秘命名函數(shù)表達(dá)式
深入理解J avaScript 系列(結(jié)局篇)
執(zhí)行上下文(Execution Contexts)
函數(shù)(Functions)
《你真懂 JavaScript 嗎?》答案詳解
設(shè)計(jì)模式之適配器模式
設(shè)計(jì)模式之組合模式
設(shè)計(jì)模式之命令模式
S.O.L.I.D 五大原則之單一職責(zé) SRP
編寫高質(zhì)量 JavaScript 代碼的基本要點(diǎn)
求值策略
閉包(Closures)
對象創(chuàng)建模式(上篇)
This? Yes,this!
設(shè)計(jì)模式之代理模式
變量對象(Variable Object)
S.O.L.I.D 五大原則之里氏替換原則 LSP
面向?qū)ο缶幊讨话憷碚?/span>
設(shè)計(jì)模式之單例模式
Function 模式(上篇)
S.O.L.I.D 五大原則之依賴倒置原則 DIP
設(shè)計(jì)模式之迭代器模式
立即調(diào)用的函數(shù)表達(dá)式
設(shè)計(jì)模式之享元模式
設(shè)計(jì)模式之原型模式
根本沒有“JSON 對象”這回事!
JavaScript 與 DOM(下)
面向?qū)ο缶幊讨?ECMAScript 實(shí)現(xiàn)
全面解析 Module 模式
對象創(chuàng)建模式(下篇)
設(shè)計(jì)模式之職責(zé)鏈模式
S.O.L.I.D 五大原則之開閉原則 OCP
設(shè)計(jì)模式之橋接模式
設(shè)計(jì)模式之策略模式
設(shè)計(jì)模式之觀察者模式
代碼復(fù)用模式(推薦篇)
作用域鏈(Scope Chain)
Function 模式(下篇)
設(shè)計(jì)模式之工廠模式

設(shè)計(jì)模式之單例模式

介紹

從本章開始,我們會(huì)逐步介紹在 JavaScript 里使用的各種設(shè)計(jì)模式實(shí)現(xiàn),在這里我不會(huì)過多地介紹模式本身的理論,而只會(huì)關(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