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

資訊專欄INFORMATION COLUMN

JavaScript 設計模式(一):單例模式

xialong / 1835人閱讀

摘要:停更許久,近期計劃更新設計模式系列。單例模式是創建型設計模式的一種。雖然它不是正規的單例模式,但不可否認確實具備類單例模式的特點。適用場景單例模式的特點,意圖解決維護一個全局實例對象。

停更許久,近期計劃更新:設計模式系列。

單例模式:限制類實例化次數只能一次,一個類只有一個實例,并提供一個訪問它的全局訪問點。

單例模式是創建型設計模式的一種。針對全局僅需一個對象的場景,如線程池、全局緩存、window 對象等。

模式特點

類只有一個實例

全局可訪問該實例

自行實例化(主動實例化)

可推遲初始化,即延遲執行(與靜態類/對象的區別)

JavaScript 是一門非正規面向對象的語言,并沒有類的定義。而單例模式要求一個 “唯一” 和 “全局訪問” 的對象,在 JavaScript 中類似全局對象,剛好滿足單例模式的兩個特點:“唯一” 和 “可全局訪問”。雖然它不是正規的單例模式,但不可否認確實具備類單例模式的特點。

// 全局對象
var globaObj = {};

使用全局變量會有以下問題:

命名空間污染(變量名沖突)

維護時不方便管控(容易不小心覆蓋)

全局變量問題折中的應對方案:

使用命名空間

閉包封裝私有變量(利用函數作用域)

ES6的 const/symbol

雖然全局變量可以實現單例,但因其自身的問題,不建議在實際項目中將其作為單例模式的應用,特別是中大型項目的應用中,全局變量的維護該是考慮的成本。

模式實現
實現方式:使用一個變量存儲類實例對象(值初始為 null/undefined )。進行類實例化時,判斷類實例對象是否存在,存在則返回該實例,不存在則創建類實例后返回。多次調用類生成實例方法,返回同一個實例對象。
“簡單版” 單例模式:
let Singleton = function(name) {
    this.name = name;
    this.instance = null;
}

Singleton.prototype.getName = function() {
    console.log(this.name);
}

Singleton.getInstance = function(name) {
    if (this.instance) {
        return this.instance;
    }
    return this.instance = new Singleton(name);
}

let Winner = Singleton.getInstance("Winner");
let Looser = Singleton.getInstance("Looser");

console.log(Winner === Looser); // true
console.log(Winner.getName());  // "Winner"
console.log(Looser.getName());  // "Winner"

代碼中定義了一個 Singleton 函數,函數在 JavaScript 中是“一等公民“,可以為其定義屬性方法。因此我們可以在函數 Singleton 中定義一個 getInstance() 方法來管控單例,并創建返回類實例對象,而不是通過傳統的 new 操作符來創建類實例對象。

this.instance 存儲創建的實例對象,每次接收到創建實例對象時,判斷 this.instance 是否有實例對象,有則返回,沒有則創建并更新 this.instance 值,因此無論調用多少次 getInstance(),最終都只會返回同一個 Singleton 類實例對象。

存在問題:

不夠“透明”,無法使用 new 來進行類實例化,需約束該類實例化的調用方式: Singleton.getInstance(...);

管理單例的操作,與對象創建的操作,功能代碼耦合在一起,不符合 “單一職責原則”

“透明版” 單例模式:

實現 “透明版” 單例模式,意圖解決:統一使用 new 操作符來獲取單例對象, 而不是 Singleton.getInstance(...)

let CreateSingleton = (function(){
    let instance;
    return function(name) {
        if (instance) {
            return instance;
        }
        this.name = name;
        return instance = this;
    }
})();
CreateSingleton.prototype.getName = function() {
    console.log(this.name);
}

let Winner = new CreateSingleton("Winner");
let Looser = new CreateSingleton("Looser");

console.log(Winner === Looser); // true
console.log(Winner.getName());  // "Winner"
console.log(Looser.getName());  // "Winner"

“透明版”單例模式解決了不夠“透明”的問題,我們又可以使用 new 操作符來創建實例對象。

“代理版“ 單例模式:

通過“代理”的形式,意圖解決:將管理單例操作,與對象創建操作進行拆分,實現更小的粒度劃分,符合“單一職責原則”

let ProxyCreateSingleton = (function(){
    let instance;
    return function(name) {
        // 代理函數僅作管控單例
        if (instance) {
            return instance;
        }
        return instance = new Singleton(name);
    }
})();

// 獨立的Singleton類,處理對象實例
let Singleton = function(name) {
    this.name = name;
}
Singleton.prototype.getName = function() {
    console.log(this.name);
}

let Winner = new PeozyCreateSingleton("Winner");
let Looser = new PeozyCreateSingleton("Looser");

console.log(Winner === Looser); // true
console.log(Winner.getName());  // "Winner"
console.log(Looser.getName());  // "Winner"
惰性單例模式

惰性單例,意圖解決:需要時才創建類實例對象。對于懶加載的性能優化,想必前端開發者并不陌生。惰性單例也是解決 “按需加載” 的問題。

需求:頁面彈窗提示,多次調用,都只有一個彈窗對象,只是展示信息內容不同。

開發這樣一個全局彈窗對象,我們可以應用單例模式。為了提升它的性能,我們可以讓它在我們需要調用時再去生成實例,創建 DOM 節點。

let getSingleton = function(fn) {
    var result;
    return function() {
        return result || (result = fn.apply(this, arguments)); // 確定this上下文并傳遞參數
    }
}
let createAlertMessage = function(html) {
    var div = document.createElement("div");
    div.innerHTML = html;
    div.style.display = "none";
    document.body.appendChild(div);
    return div;
}

let createSingleAlertMessage = getSingleton(createAlertMessage);
document.body.addEventListener("click", function(){
    // 多次點擊只會產生一個彈窗
    let alertMessage = createSingleAlertMessage("您的知識需要付費充值!");
    alertMessage.style.display = "block";
})

代碼中演示是一個通用的 “惰性單例” 的創建方式,如果還需要 createLoginLayer 登錄框, createFrame Frame框, 都可以調用 getSingleton(...) 生成對應實例對象的方法。

適用場景

“單例模式的特點,意圖解決:維護一個全局實例對象。”

引用第三方庫(多次引用只會使用一個庫引用,如 jQuery)

彈窗(登錄框,信息提升框)

購物車 (一個用戶只有一個購物車)

全局態管理 store (Vuex / Redux)

項目中引入第三方庫時,重復多次加載庫文件時,全局只會實例化一個庫對象,如 jQuerylodashmoment ..., 其實它們的實現理念也是單例模式應用的一種:

// 引入代碼庫 libs(庫別名)
if (window.libs != null) {
  return window.libs;    // 直接返回
} else {
  window.libs = "...";   // 初始化
}
優缺點

優點:適用于單一對象,只生成一個對象實例,避免頻繁創建和銷毀實例,減少內存占用。

缺點:不適用動態擴展對象,或需創建多個相似對象的場景。

TIPS: 多線程編程語言中,單例模式會涉及同步鎖的問題。而 JavaScript 是單線程的編程語言,暫可忽略該問題。

參考文章

《JavaScript 設計模式》

《JavaScript 設計模式與開發實踐》

《JavaScript 設計模式系統講解與應用》

本文首發Github,期待Star!
https://github.com/ZengLingYong/blog

作者:以樂之名
本文原創,有不當的地方歡迎指出。轉載請指明出處。

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

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

相關文章

  • JavaScript設計模式單例模式

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

    zhaot 評論0 收藏0
  • JavaScript設計模式與開發實踐 | 04 - 單例模式

    摘要:觀察構造函數的代碼,該構造函數實際上負責了兩件事情第一是創建對象和執行初始化方法,第二是保證只有一個對象。惰性單例在實際開發中非常有用,是單例模式的重點。 單例模式 單例模式的定義是: 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 單例模式是一種常用的模式,有一些對象我們往往只需要一個,比如線程池、全局緩存、瀏覽器的window對象等。例如,當我們點擊登錄按鈕時,頁面會彈出一...

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

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

    Clect 評論0 收藏0
  • JavaScript設計模式-第部分:單例模式、組合模式和外觀模式

    摘要:但是,這并不是采用單例的唯一原因。使用命名空間單例模式也被稱為模塊設計模式。函數內部聲明了一些局部函數和或變量。緊隨函數聲明放置即可立即執行外部函數,并將所得的對象文字費賠給變量。 JavaScript設計模式-第一部分:單例模式、組合模式和外觀模式 設計模式是一些可靠的編程方式,有助于保證代碼更加易于維護、擴展及分離,所有設計模式在創建大型JavaScript應用程序時均不可或缺 單...

    betacat 評論0 收藏0
  • JavaScript設計模式學習—單例模式

    摘要:什么是單例模式簡單點來說,單例模式就是確保某個類只有一個實例,并且最好只被創建過一次。對計算機來說,像打印機,線程池都是經典的單例模式。 什么是單例模式 簡單點來說,單例模式就是確保某個類只有一個實例,并且最好只被創建過一次。對計算機來說,像打印機,線程池都是經典的單例模式。對于JavaScript所處的前端環境來說,像登錄懸浮框,在整個頁面中只會有一個,無論用戶點擊多少次,只會被創建...

    TerryCai 評論0 收藏0

發表評論

0條評論

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