国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

單例模式 | 程序員都想要探索的 Javascript 設計模式

rottengeek / 3433人閱讀

摘要:單例模式主要是為了解決對象的創建問題。頁面中只放一個按鈕登錄實現得到登錄框元素綁定事件關閉彈框這里做登錄點擊頁面中的按鈕每次讓登錄框出現即可上面的代碼根據單例模式的使用構造函數來實現的。


最近打算系統的學習 Javascript 設計模式,以便自己在開發中遇到問題可以按照設計模式提供的思路進行封裝,這樣可以提高開發效率并且可以預先規避很多未知的問題。

先從最基本的單例模式開始
什么是單例模式
單例模式,從名字拆分來看,單指的是一個,例是實例,意思是說多次通過某個類創造出來實例始終只返回同一個實例,它限制一個類只能有一個實例。單例模式主要是為了解決對象的創建問題。單例模式的特點:
1、一個類只有一個實例
2、對外提供唯一的訪問接口
在一些以類為核心的語言中,例如java,每創建一個對象就必須先定義一個類,對象是從類創建而來。js是一門無類(class-free)的語言,在js中創建對象的方法非常簡單,不需要先定義類即可創建對象。
在js中,單例模式是一種常見的模式,例如瀏覽器中提供的window對象,處理數字的Math對象。
單例模式的實現
1
對象字面量
在js中實現單例最簡單的方式是創建對象字面量,字面量對象中可以包含多個屬性和方法。
var mySingleton = {

attr1:1,
attr2:2,
method:function (){
    console.log("method");    
}

}
以上創建一個對象,放在全局中,就可以在任何地方訪問,要訪問對象中的屬性和方法,必須通過mySingleton這個對象,也就是說提供了唯一一個訪問接口。
2
使用閉包私有化
擴展mySingleton對象,添加私有的屬性和方法,使用閉包的形式在其內部封裝變量和函數聲明,只暴露公共成員和方法。
var mySingleton = (function (){

 //私有變量

var privateVal = "我是私有變量";

//私有函數

function privateFunc(){

    console.log("我是私有函數");    

}

return {            
        attr1:1,            
        attr2:2,            
        method:function (){                                                                   console.log("method");        
                   privateFunc();
       }
   }    

})()
把privateVal和privateVal被封裝在閉包產生的作用域中,外界訪問不到這兩個變量,這避免了對全局命名污染。
3
惰性單例
無論使用對象字面量或者閉包私有化的方式創建單例,都是在腳本一加載就被創建。有時候頁面可能不會用到這個單例對象,這樣就會造成資源浪費。對于這種情況,最佳處理方式是使用惰性單例,也就是在需要這個單例對象時再初始化。
var mySingleton = (function (){

function init(){
    //私有變量
    var privateVal = "我是私有變量";
    //私有函數
    function privateFunc(){
        console.log("我是私有函數");    
    }

    return {
        attr1:1,
        attr2:2,
        method(){
            console.log("method");    
            privateFunc();
        }
    }
}

//用來保存創建的單例對象
 var instance = null;
return {
    getInstance (){
        //instance沒有存值,就執行函數得到對象
        if(!instance){
            instance = init();
        }    
        //instance存了值,就返回這個對象
        return instance;
    }
}

})();

//得到單例對象
var singletonObj1 = mySingleton.getInstance();
var singletonObj2 = mySingleton.getInstance();

console.log( singletonObj1 === singletonObj2 ); //true

程序執行后,將創建單例對象的代碼封裝到init函數中,只暴露了獲取單例對象的函數getInstance。當有需要用到時,通過調用函數mySingleton.getInstance()得到單例對象,同時使用instance將對象緩存起來,再次調用mySingleton.getInstance()后得到的是同一個對象,這樣通過一個函數不會創建多個對象,起到節省資源的目的。
4
使用構造函數
可以使用構造函數的方式,創造單例對象:
function mySingleton(){

//如果緩存了實例,則直接返回
if (mySingleton.instance) {
    return mySingleton.instance;
}

//當第一次實例化時,先緩存實例
mySingleton.instance = this;

}

mySingleton.prototype.otherFunc = function (){

console.log("原型上其他方法");    

}

var p1 = new mySingleton();
var p2 = new mySingleton();

console.log( p1 === p2 ); //true

當第一次使用new調用函數創建實例時,通過函數的靜態屬性mySingleton.instance把實例緩存起來,在第二次用new調用函數,判斷實例已經緩存過了,直接返回,那么第一次得到的實例p1和第二次得到的實例p2是同一個對象。這樣符合單例模式的特點:一個類只能有一個實例。
這樣做有一個問題,暴露了可以訪問緩存實例的屬性mySingleton.instance,這個屬性的值可以被改變:
var p1 = new mySingleton();
//改變mySingleton.instance的值
//mySingleton.instance = null;
//或者
mySingleton.instance = {};
var p2 = new mySingleton();
console.log( p1 === p2 ); //false
改變了mySingleton.instance值后,再通過new調用構造函數創建實例時,又會重新創建新的對象,那么p1和p2就不是同一個對象,違反了單例模式一個類只能有一個實例。
閉包中的實例
不使用函數的靜態屬性緩存實例,而是重新改寫構造函數:
function mySingleton(){

//緩存當前實例
var instance  = this;

//執行完成后改寫構造函數
mySingleton = function (){
    return instance;    
}
//其他的代碼
instance.userName = "abc";

}

mySingleton.prototype.otherFunc = function (){

console.log("原型上其他方法");    

}

var p1 = new mySingleton();
var p2 = new mySingleton();

console.log( p1 === p2 ); //true

第一次使用new調用函數創建實例后,在函數中創建instance用來緩存實例,把mySingleton改寫為另一個函數。如果再次使用new調用函數后,利用閉包的特性,返回了緩存的對象,所以p1和p2是同一個對象。
這樣雖然也可以保證一個類只返回一個實例,但注意,第二次再次使用new調用的構造函數是匿名函數,因為mySingleton已經被改寫:
//第二次new mySingleton()時這個匿名函數才是真正的構造函數
mySingleton = function (){

return instance;    

}
再次給原mySingleton.prototype上添加是屬性,實際上這是給匿名函數的原型添加了屬性:
var p1 = new mySingleton();

//再次給mySingleton的原型上添加屬性
mySingleton.prototype.addAttr = "我是新添加的屬性";

var p2 = new mySingleton();

console.log(p2.addAttr); //undefined

對象p2訪問屬性addAttr并沒有找到。通過一個構造函數構造出來的實例并不能訪問原型上的方法或屬性,這是一種錯誤的做法,還需要繼續改進。
function mySingleton(){

var instance;
//改寫構造函數
mySingleton = function (){
    return instance;    
}
//把改寫后構造函數的原型指向this

mySingleton.prototype = this;

//constructor改寫為改寫后的構造函數
mySingleton.prototype.constructor = mySingleton;

//得到改寫后構造函數創建的實例
instance = new mySingleton;

//其他的代碼
instance.userName = "abc";

//顯示的返回改寫后構造函數創建的實例
return instance;

}

mySingleton.prototype.otherFunc = function (){

console.log("原型上其他方法");    

}

var p1 = new mySingleton();

//再次給mySingleton的原型上添加屬性
mySingleton.prototype.addAttr = "我是新添加的屬性";

var p2 = new mySingleton();
console.log(p2.addAttr); //"我是新添加的屬性"
console.log( p1 === p2 ); //true

以上代碼主要做了以下幾件事:
數字列表改寫 mySingleton 函數為匿名函數
改寫 mySingleton 的原型為第一次通過 new 創建實例
因為改寫了 prototype,要把 constructor 指回mySingleton
顯式返回通過改寫后 mySingleton 構造函數構造出的實例
無論使用多少次new調用mySingleton這個構造函數,都返回同一個對象,并且這些對象都共享同一個原型。
實踐單例模式
1
使用命名空間
根據上述,在js中創建一個對象就是一個單例,把一類的方法和屬性放在對象中,都通過提供的全局對象訪問。
var mySingleton = {

attr1:1,
attr2:2,
method:function (){
    console.log("method");    
}

}
這樣的方式耦合度極高,例如:要給這個對象添加屬性:
mySingleton.width = 1000; //添加一個屬性

//添加一個方法會覆蓋原有的方法
mySingleton.method = function(){};
如果在多人協作中,這樣添加屬性的方式經常出現被覆蓋的危險,可以采用命名空間的方式解決。
/A同學
mySingleton.a = {};
mySingleton.a.method = function(){}
//訪問
mySingleton.a.method();

//B同學
mySingleton.b = {};
mySingleton.b.method = function(){}
//訪問
mySingleton.b.method();
都在自己的命名空間中,覆蓋的幾率會很小。
可以封裝一個動態創建命名空間的通用方法,這樣在需要獨立的命名空間時只需要調用函數即可。
mySingleton.namespace = function(name){

var arr = name.split(".");
//存一下對象
var currentObj = mySingleton;
for( var i = 0; i < arr.length; i++ ){
    //如果對象中不存在,則賦值添加屬性
    if(!currentObj[arr[i]]){
        currentObj[arr[i]] = {};
    }
    //把變量重新賦值,便于循環繼續創建命名空間
    currentObj = currentObj[arr[i]]
}

}

//創建命名空間
mySingleton.namespace("bom");
mySingleton.namespace("dom.style");
以上調用函數生成命名空間的方式代碼等價于:
mySingleton.bom = {};
mySingleton.dom = {};
mySingleton.dom.style = {};
2
單例登錄框
使用面向對象實現一個登錄框,在點擊登錄按鈕后登錄框被append到頁面中,點擊關閉就將登錄框從頁面中remove掉,這樣頻繁的操作DOM不合理也不是必要的。

只需要在點擊關閉時隱藏登錄框,再次點擊按鈕后,只需要show出來即可。
頁面中只放一個按鈕:

js實現:
function Login(){

var instance;

Login = function(){
    return install;
}

Login.prototype = this;
install = new Login;
install.init();
return install;

}

Login.prototype.init = function(){

//得到登錄框元素
this.Login = this.createHtml();
document.body.appendChild(this.Login);
//綁定事件
this.addEvent();

}
Login.prototype.createHtml = function(){

var LoginDiv = document.createElement("div");
LoginDiv.className = "box";
var html = `

這里做登錄

` LoginDiv.innerHTML = html; return LoginDiv;

}
Login.prototype.addEvent = function(){

var close = this.Login.querySelector(".close");
var _this = this;
close.addEventListener("click",function(){
    _this.Login.style.display = "none";
})

}
Login.prototype.show = function(){

this.Login.style.display = "block";

}
//點擊頁面中的按鈕
var loginBtn = document.querySelector("#loginBtn");
loginBtn.onclick = function(){

var login = new Login();
//每次讓登錄框出現即可
login.show();

}

上面的代碼根據單例模式的使用構造函數來實現的。這樣在一開始生成了一個對象,之后使用的都是同一個對象。

總結
單例模式是一種非常實用的模式,特別是懶性單例技術,在合適時候創建對象,并且只創建唯一一個,這樣減少不必要的內存消耗。
正在學習設計模式,不正確的地方歡迎拍磚指正。

公眾號ID:Miaovclass
關注妙味訂閱號:“妙味前端”,為您帶來優質前端技術干貨;

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98680.html

相關文章

  • 探索Javascript設計模式---單例模式

    摘要:單例模式主要是為了解決對象的創建問題。頁面中只放一個按鈕登錄實現得到登錄框元素綁定事件關閉彈框這里做登錄點擊頁面中的按鈕每次讓登錄框出現即可上面的代碼根據單例模式的使用構造函數來實現的。 最近打算系統的學習javascript設計模式,以便自己在開發中遇到問題可以按照設計模式提供的思路進行封裝,這樣可以提高開發效率并且可以預先規避很多未知的問題。 先從最基本的單例模式開始。 什么是單例...

    Hanks10100 評論0 收藏0
  • JavaScript設計模式單例模式

    摘要:此時我們創建的對象內保存靜態變量通過取值器訪問,最后將這個對象作為一個單例放在全局空間里面作為靜態變量單例對象供他人使用。 單例模式 又被稱為單體模式,是只允許實例化一次的對象類。有時我們也用一個對象來規劃一個命名空間,井井有條的管理對象上面的屬性和方法。 傳統的面向對象語言中單例模式的實現,均是單例對象從類中創建而來,在以類為中心的語言中,這是很常見的做法。如果需要某個對象,就必須先...

    zhaot 評論0 收藏0
  • 設計模式1

    摘要:模式是什么設計模式是在軟件設計過程中針對特定問題的簡潔而優雅的解決方案。模式的意義設計模式的意義是讓人們寫出可復用和可維護性高的程序。所有設計模式的實現都遵循一條原則,即找出程序中變化的地方,并將變化封裝起來。 模式是什么 設計模式是:在軟件設計過程中針對「特定」問題的「簡潔而優雅」的解決方案。 在軟件開發的歷史中,沉淀了一些好的軟件設計,而設計模式便是給這些好設計取了個名字。「好的設...

    reclay 評論0 收藏0
  • JS設計模式-單例模式

    摘要:單例模式單例模式,也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。透明的單例模式利用一個形成一個閉包,在里邊通過變量來記錄實例,并返回構造函數。 單例模式 單例模式,也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。 ———來自維基百科 一個很典型的應用是在點擊登錄按鈕,彈出登錄浮窗,不論...

    Doyle 評論0 收藏0
  • 再遇設計模式JavaScript

    摘要:在面向對象的語言中,比如,等,單例模式通常是定義類時將構造函數設為,保證對象不能在外部被出來,同時給類定義一個靜態的方法,用來獲取或者創建這個唯一的實例。 萬事開頭難,作為正經歷菜鳥賽季的前端player,已經忘記第一次告訴自己要寫一些東西出來是多久以的事情了。。。如果,你也和我一樣,那就像我一樣,從現在開始,從看到這篇文章開始,打開電腦,敲下你的第一篇文章(或者任何形式的文字)吧。 ...

    Clect 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<