聽飛狐聊JavaScript設計模式系列06

本回內容介紹

上一回聊到JS中模擬接口,裝飾者模式,摻元類,分析了backbone的繼承源碼,感受還好吧!javascript

介一回,偶們來聊一下在JS單例模式(singleton),單例模式其實運用很普遍,好比:jquery,AngularJS,underscore吖蝦米的都是單例模式,來吧,直接開始咯:java

1. 單例模式

保證一個類只有一個實例,從全局命名空間裏提供一個惟一的訪問點來訪問該對象。其實以前寫過的對象字面量也是一種簡單單例,以下:jquery

var Singleton = {
        name: "飛狐",
        method: function () {
            return 'hello world';
        }
    };
    alert(Singleton.method());    // 返回hello world

這就是一個簡單單例了,應該不少盆友已經看出來了,沒有做用域,若是要擴展私有屬性和方法的話,那麼就能夠靠閉包來實現。android

2. 閉包單例模式

顧名思義要用到閉包,做爲返回實例對象,以下:web

var Singleton = (function(){
        var name = '飛狐';    // 私有屬性
        var nickname = '帥狐';
        var showNickname = function(){    // 私有方法
            return nickname;
        }
        return {    // 返回一個對象
            name:name,    // 將私有屬性公開
            nickName: function(){    // 在公開的方法中返回私有方法
                return showNickname();
            }
        }
    })();
    alert(Singleton.name);    // 飛狐 
    alert(Singleton.nickName());    // 帥狐

這裏咱們接着上邊兒簡單單例的例子來,稍微的改一下,改爲閉包以後,就數據保證了不受外界干擾了。windows

3. 惰性單例模式

惰性單例就是隻有在使用的時候才初始化,以下:瀏覽器

var Singleton = (function(){
        var uniq;    // 私有變量,用來存放返回實例化對象的容器
        function init(){    // 初始化方法    
            var buildeList = function(){    // 私有方法
                // 下面這一堆就是建立一個有序列表,含有5個li
                var root = document.createElement('ol');
                document.body.appendChild(root);
                for(var i=0;i<5;i++){
                    var a = document.createElement('a');
                    a.innerHTML = '<a>帥狐</a>';
                    var li = document.createElement('li');
                    li.appendChild(a);
                    root.appendChild(li);
                }
            }
            
            return {    // 同樣的閉包,暴露共有方法
                method:function(){
                    return buildeList();
                }
            };
        }
        
        return {
            // 這裏就是實例化對象了
            getInstance:function(){
                // 這裏的uniq爲true的時候,或者能夠寫成 typeof uniq==='undefined'
                if(!uniq){
                    // 建立單例實例
                    uniq = init();
                }
                return uniq;
            }
        };
    })();
    
    Singleton.getInstance().method();    // 返回1.帥狐2.帥狐3.帥狐4.帥狐5.帥狐

這個例子就是惰性單例了,也就是說只有在用的時候纔會去初始化方法,這樣能夠更省資源。閉包

4. 分支單例模式

分支單例就很簡單了,就是作程序分支的判斷,利用分支來返回相應的實例,常常用於瀏覽器檢測,直接看代碼吧,以下:app

var ua  = window.navigator.userAgent.toLocaleLowerCase();
    var matchedRE = /iphone|android|symbianos|windows\sphone/g;
    var Singleton = (function() {
          var webUrl = 'web端url';
          var mobileUrl = '移動端url';
          return (matchedRE.test(ua))?mobileUrl:webUrl;
    })();
    // 若是是pc端返回就是web端url,若是是移動端就返回移動端url
    alert(Singleton);

這個例子就是分支單例了,比較簡單,這個例子也是模擬京東目前判斷訪問設備的代碼。iphone

裝逼圖
裝個逼再說。剛看到一新聞,韓雪發微博稱,由於本身修改的本月套餐,上月流量就清零了,並稱:「我改這個月的和上個月有什麼關係嗎?我付了錢的,多餘的流量憑什麼你說清零就清零呢?這不是霸王條款嗎?」,女神都忍受不了了,哈哈~~

這一回講的內容很少,就一個單例模式,
下面的內容更簡單,一道題。

5. 筆試題:判斷字符串中出現次數最多的字母,返回該字母及其出現次數

function calculate(str){
        //命名一個變量放置字母出現的最高次數並初始化爲0
        var maxLength = 0;
        //命名一個變量放置結果輸入 
        var result = '';
        //循環迭代開始,並判斷字符串是否爲空
        while(str != '' ){
            //將原始的字符串變量賦值給新變量
            var oldStr = str;
            //用字符串的substr的方法獲得第一個字符(首字母)
            var getStr = str.substr(0,1);
            //執行一次全局替換
            eval("str = str.replace(/"+getStr+"/g,'')");
            //判斷原始的字符串的長度減去替代後字符串長度是否大於以前出現的最大的字符串長度
            if(oldStr.length-str.length > maxLength ) {
                //兩字符串長度相減獲得最大的字符串長度
                maxLength = oldStr.length-str.length;
                //返回最大的字符串結果(字母、出現次數)
                result = "出現最多的字母是:" + getStr + "------出現了" + maxLength + " 次。";
            }
        }
        return result;
    }
    var str ="adadfdfseffserfefsefseeffffftsdg";
    alert(calculate(str));

這個題基本上我都寫了註釋,難度適中,當娛樂消遣。

這一回,主要聊了單例模式,應該很好理解,難度不大。
下一回,咱主要聊一聊工廠模式。

話說,看完文章以爲ok,客觀點個讚唄,好東西多推薦推薦,讓你們都知道,嘿嘿,好像有點那啥賣瓜了...


注:此係飛狐原創,轉載請註明出處

相關文章
相關標籤/搜索