js設計模式中單例模式的簡要說明

一. 認識單例模式

單例模式的意思是,保證一個類隻有一個實例,並且有一個接口供全局訪問。它的作用就是防止頻繁創建實例,浪費不必要的內存空間和資源消耗,那它有什麼實用場景呢,假如我們在頁面中有一個點擊跳出一個彈窗操作,彈窗應該是唯一的,無論點擊多少次它都應該被構建一次,那麼這個彈窗就適合用單例模式來創建。

二. 單例模式的分類  

簡單實現單例模式透明實現單例模式代理實現單例模式js單例模式惰性單例模式通用惰性單例模式(主要用於 js) 

註: 前三種單例模式為用類實現的思想,通過 new 的方式來創建實例,而 javascript 是沒有類的,可以直接創建實例,因此並不適用,主要用於後邊三種。

三. 具體實現和思想學習 

1. 簡單實現單例模式

        let Singleton = function ( name ) {
            this.name = name;
        }
        Singleton.instance = null;
        Singleton.prototype.getName  = function () {
            console.log( this.name )
        }
        Singleton.getInstance = function ( name ) {
            if( !this.instance ) {
                this.instance = new Singleton( name );
            }
            return this.instance;
        }
 
        let a = Singleton.getInstance('sk');
        let b = Singleton.getInstance('ss');
        console.log(a);
        console.log(a === b) // true

實現思想:將第一次創建的實例進行保存,之後再次創建前判斷是否已經創建,如果之前創建過則返回已經保存的實例,否則創建一個實例,將實例創建和判斷封裝到瞭一個 getInstance 函數中,這種方式相對簡單,但增加瞭類的“不透明性”,用一個函數來獲取一個實例,而不是以往通過 new 來創建。

2. 透明單例模式

        let CreateDiv = function () {
            let instance ;
            let CreateDiv = function ( html ) {
                if( instance ) {
                    return instance;
                }
                this.html = html;
                this.init();
                return instance = this;
            }
            
            CreateDiv.prototype.init = function () {
                let element = document.createElement('div');
                element.innerHTML = this.html;
                document.body.appendChild(element);
            }
            return CreateDiv;
        }();
 
        let a = new CreateDiv('石頭山');
        let b = new CreateDiv('哈哈');
        console.log(a === b); // true 

實現思想:該方式與前一實現不同的在於用 new 來創建實例,運用瞭閉包來保存實例標識,從而達到隻能創建唯一實例,但是如果有一天想創建多個 div 實例,該代碼就不實用瞭,必須修改代碼,因此擴展除瞭代理實現。

3. 代理實現單例模式

        let CreateDiv = function ( html ) {
            this.html = html;
            this.init();
        }
        CreateDiv.prototype.init = function () {
            let div = document.createElement('div');
            div.innerHTML = this.html;
            document.body.appendChild(div);
        }
 
        let ProxySingletonCreateDiv = function () {
            let instance ;
            return function ( html ) {
                if( !instance ) {
                    instance = new CreateDiv( html );
                }
                return instance;
            }
        }();
        let a = new ProxySingletonCreateDiv('sven1');      
        let b = new ProxySingletonCreateDiv('sven2');
        console.log(a === b); // true

實現思想:CreateDiv 為一個普通類,將創建和判斷唯一實例封裝在瞭代理函數中,增加瞭代碼復用性,彌補瞭透明單例的不足,需要單例則直接 new ProxySingletonCreateDiv(),需要普通實例則直接 new CreateDiv(),但是該方式代碼可讀性差,也不采用。

4. js的單例模式

① 使用命名空間來創建:將所有變量和方法直接放在一個全局對象中

 let S = {
            name: '石頭山',
            getName() {
                console.log(this.name);
            }
        }

② 使用閉包封裝私有變量:將變量封裝在閉包內部,隻向全局暴露一個訪問接口

            let name = "石頭山";
            return {
                getName() {
                    return name;
                }
            }
        }

5. 通用惰性單例

        // 寫一個通用的獲取單例的函數 , fn 為執行單次的函數
        let getSingle = function ( fn ) {
            let result;
            return function () {
                return result || ( result = fn.apply(this, arguments))
            }
        }
        // 綁定事件
        let bindEvent = function () {
            document.getElementById('div').addEventListener('click',()=>{
                console.log('我出現瞭')
            });
        }();
        // 無論渲染多少次,事件隻綁定一次
        let render = function () {
            console.log('開始渲染!');  
            getSingle(bindEvent)
        }
        render();
        render();
        render();

該方式是 js 中常用的單例實現方法,再頁面重復渲染三次時,監聽事件隻綁定瞭一次,減少瞭開銷。

惰性體現:惰性體現在實例實在需要時創建,並不會在頁面加載好就創建。

實現思想:首先利用閉包和高階函數封裝瞭一個返回單一實例的函數,其參數就是一個隻執行一次的函數,可以隨時改變單例的作用,大大增加瞭代碼的可復用性。

四. 總結

單例模式是一種簡單但非常使用的開發模式,js 開發中,通用惰性單例實現方式最常用的一中方式,它將創建對象和管理單例的職責封裝在兩個不同的方法中,組合在一起就具有瞭單例模式的威力。

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: