成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

javascript中的設(shè)計模式(一)

chaosx110 / 2538人閱讀

摘要:模式迭代器模式顧名思義,迭代器可以將對于一個聚合對象內(nèi)部元素的訪問與業(yè)務(wù)邏輯分離開。模式組合模式組合模式將對象組合成樹形結(jié)構(gòu),以表示層級結(jié)構(gòu)。重點是,葉結(jié)點與中間結(jié)點有統(tǒng)一借口。本文總結(jié)自設(shè)計模式與開發(fā)實踐,曾探著

模式1 - 單例模式

單例模式的核心是確保只有一個實例,并且提供全局訪問。

特點:

滿足“單一職責(zé)原則” : 使用代理模式,不在構(gòu)造函數(shù)中判斷是否已經(jīng)創(chuàng)建過該單例;

滿足惰性原則

應(yīng)用:
彈出登陸窗口。

實例:

var getSingle = function (fn) {
    var res;
    return function() {
        return res || (res = fn.apply(this, arguments));
    }
}

var createPopup() {
    var div = document.createElement("div");
    div.innerHTML = "Login window";
    div.style.display = "none"; 
    document.body.appendChild(div);
    return div;
}

var createLoginPopup = getSingle(createPopup);            //create popup div here by using a given function, 滿足兩個原則 

document.getElementById("loginBt").onclick = function() {
    var popup = createLoginPopup();
    pop.style.display = "block";
}

模式2 - 策略模式

定義一個個可以相互替換的算法,并且把他們封裝起來。

特點:

符合開放-封閉原則 : 要修改使用的算法時不用深入函數(shù)內(nèi)部進(jìn)行修改,只需修改策略類;

將算法的實現(xiàn)與使用分離開,提高算法復(fù)用性;

通過組合、委托和多態(tài)避免多重條件選擇語句;

應(yīng)用:
動畫實現(xiàn)不同的緩動效果。

一般分為兩個部分:策略類于環(huán)境類。策略類用于封裝各種算法,并且負(fù)責(zé)具體的計算過程; 環(huán)境類負(fù)責(zé)接收用戶的請求,并且把請求委托給某一個策略類。因為各個策略類實現(xiàn)的算法和計算的結(jié)果不同,而環(huán)境類調(diào)用策略類的方法卻是相同的,這就體現(xiàn)了多態(tài)性。要想實現(xiàn)不同的算法,只需要替換環(huán)境類中的策略類即可。

在js中,我們不必構(gòu)造策略類,可直接使用函數(shù)作為策略對象。

示例:

var strategies = {
    "s1": function() {
        //algo 1
    },
    "s2": function() {
        //algo 2
    }, 
    "s3": function() {
        //algo 3
    }
 }
 
 var someContext =  new SomeConext();
 someContext.start("s1");  //using s1 to calculate
 //someContext.add("s1");  or add s1 as a rule for validation
 

模式3 - 代理模式

代理就像一個經(jīng)紀(jì)人,當(dāng)用戶不方便直接訪問某個對象或者需要對訪問進(jìn)行一些過濾/加工時,可以通過代理來進(jìn)行對象訪問。代理會對請求進(jìn)行一些處理,然后再將請求傳遞給本體。

一般分為保護(hù)代理和虛擬代理:

保護(hù)代理負(fù)責(zé)過濾掉一些請求;

虛擬代理則是將一些花銷比較大的操作延遲到真正他的時候再去創(chuàng)建,例如new一個對象。

特點:

保證對象符合單一職責(zé)原則;

應(yīng)用:
圖片預(yù)加載, 合并http請求, 惰性加載, 緩存代理(避免重復(fù)計算,可以寫一個通用的緩存對象(其實就是一個閉包),將高階函數(shù)作為參數(shù)傳入)。

模式4 - 迭代器模式

顧名思義,迭代器可以將對于一個聚合對象內(nèi)部元素的訪問與業(yè)務(wù)邏輯分離開。

一般分為內(nèi)部迭代器和外部迭代器:

內(nèi)部迭代器只需一次初始調(diào)用,不需要關(guān)心迭代器的內(nèi)部實現(xiàn);

外部迭代器需要顯式地請求下一個元素,因此可以手工控制迭代過程和順序,例如調(diào)用iterator.next();

無論是哪種迭代器,只要聚合對象有l(wèi)ength屬性并且可以通過下標(biāo)訪問,那么就可以被迭代。因此類數(shù)組對象及字面量對象(用for in)都可以。

絕大部分語言都內(nèi)置了迭代器。

應(yīng)用:
可以通過添加終止條件來中斷迭代:在callback函數(shù)中判斷,如果return值為false,則通過break跳出迭代循環(huán)。
由此可以設(shè)計根據(jù)瀏覽器類型創(chuàng)建的返回對象,按優(yōu)先級一個個迭代。

模式5 - 訂閱發(fā)布模式

將許多對象弱耦合起來,當(dāng)一個對象的狀態(tài)發(fā)生變化時,所有訂閱了該變化的對象都會收到通知。
DOM事件是典型的訂閱發(fā)布模式,同時我們還可以自定義事件:

var event = {
    clients : {},
    listen : function (signal,fn){
        if(!this.clients[signal]) {
            this.clients[signal] = [];
        }
        this.clients[signal].push(fn);    
    },
    trigger: function (arguments){  //not only trigger the event, but also send some data
        var sig = Array.prototype.shift.call(arguments);
        fns = this.clients[sig];
        
        if(!fns || fns.length === 0)  return false;
        for(var i = 0; i < fns.length; i++) {
            var fn = fns[i];
            fn.apply(this, arguments);
        }
    },
    remove:  function (signal,fn){
        var fns = this.clients[signal];
        if(!fns)  return false;
        if(!fn) {   
            //remove all fns
            delete this.clients[signal];
        } else {
            for(var i = 0; i 

可以通過離線消息棧來保存沒有被訂閱的但是發(fā)生了的事件,等到有人訂閱再依次取出執(zhí)行。

應(yīng)用:
網(wǎng)站登錄-當(dāng)用戶登錄成功并且ajax返回數(shù)據(jù)后,trigger事件,需要用到用戶數(shù)據(jù)的渲染模塊訂閱該事件。

模式6-命令模式

可以解決請求發(fā)送者和請求接受者之間的耦合關(guān)系。實際上,我們只需要調(diào)用command對象中的execute方法就行,他會自動調(diào)用命令接收者對應(yīng)的命令。

示例:

var tv = {
    open: function() {
        console.log("open tv");
    },
    close: function() {
        console.log("turn off tv");
    },
    nextChannel: function() {
        console.log("next channel");
    }
}

//相當(dāng)于我把receiver的一些可用操作封裝到command對象里了,并且提供了統(tǒng)一的接口
var openTVCmd = function(receiver) {
    return {
        execute: function(){
            receiver.open();
        },
        undo : function() {
            //go to previous channel
            
        }
    }
}

var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");

var setCmd = function(button, cmd) {
    button.onclick = function(){
        cmd.execute();
    }
}

var opentvcmd = new openTVCmd();
setCmd(btn1, opentvcmd);
btn2.onclick = function(){    //undo command
    opentvcmd.undo();
}

應(yīng)用:

可實現(xiàn)命令的撤銷和重做,只需紀(jì)錄一個oldState或者使用一個緩存來存放歷史命令;

可實現(xiàn)命令隊列,將command對象壓入堆棧,只需依次調(diào)用他們的execute函數(shù),由此可實現(xiàn)宏命令;

可分為智能命令和傻瓜命令:
1.智能命令不需要知道receiver,可自己完成請求,代碼上類似策略模式,但目的不同;
2.傻瓜命令則只負(fù)責(zé)將請求傳遞給真正的receiver。

模式7-組合模式

組合模式將對象組合成樹形結(jié)構(gòu),以表示層級結(jié)構(gòu)。借助于對象的多態(tài)性,它使得用戶可以統(tǒng)一地對待組合對象(單個對象的組合)和單個對象。

應(yīng)用:

可實現(xiàn)宏命令,只需要調(diào)用根結(jié)點的execute,程序會自動遍歷整棵樹并依次執(zhí)行各中間節(jié)點和葉結(jié)點的execute函數(shù)。重點是,葉結(jié)點與中間結(jié)點有統(tǒng)一借口。

可用來模擬文件和文件夾層級結(jié)構(gòu):

示例:

var Folder = function(name) {
    this.name = name;
    this.files = [];
}
Folder.prototype.add = function(file) {
    this.files.push(file);
}
Folder.prototype.scan = function() {
    console.log("begin scanning folder "+ this.name);
    for(var i=0; i

注意,層級1與層級2結(jié)點之間并非父子關(guān)系,只是因為他們有統(tǒng)一的借口而被聯(lián)系在一起。
可以對這兩種結(jié)點建立雙向映射,即使文件1里面含有其父結(jié)點的引用,這樣子在刪除一個文件時就需要將其在其父結(jié)點的files中刪除。

組合模式使得用戶可以忽略組合對象和單個對象的差異而統(tǒng)一對待,但這也會使得每個對象看上去都差不多,增加代碼理解的難度。

P.s. 本文總結(jié)自《JavaScript設(shè)計模式與開發(fā)實踐》,曾探著

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/91264.html

相關(guān)文章

  • JS程序

    摘要:設(shè)計模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計模式必須要先搞懂面向?qū)ο缶幊?,否則只會讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識只有分享才有存在的意義。 是時候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評論0 收藏0
  • 理解JavaScript的核心知識點:原型

    摘要:首先,需要來理清一些基礎(chǔ)的計算機編程概念編程哲學(xué)與設(shè)計模式計算機編程理念源自于對現(xiàn)實抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過程式和函數(shù)式編程。 JavaScript 中的原型機制一直以來都被眾多開發(fā)者(包括本人)低估甚至忽視了,這是因為絕大多數(shù)人沒有想要深刻理解這個機制的內(nèi)涵,以及越來越多的開發(fā)者缺乏計算機編程相關(guān)的基礎(chǔ)知識。對于這樣的開發(fā)者來說 J...

    iKcamp 評論0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠矶际侵械闹鲗?dǎo)范式。函數(shù)式編程是一種強調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠矶际荍avaScript中的主導(dǎo)范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數(shù)式編程越來越多得受到開發(fā)者的青睞。函數(shù)式編程是一種強調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。因此,...

    cfanr 評論0 收藏0
  • 前端每周清單半年盤點之 JavaScript

    摘要:前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點分為新聞熱點開發(fā)教程工程實踐深度閱讀開源項目巔峰人生等欄目。背后的故事本文是對于年之間世界發(fā)生的大事件的詳細(xì)介紹,闡述了從提出到角力到流產(chǎn)的前世今生。 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點;分為新聞熱點、開發(fā)教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡迎...

    Vixb 評論0 收藏0
  • 前端練級攻略(第二部分)

    摘要:是文檔的一種表示結(jié)構(gòu)。這些任務(wù)大部分都是基于它。這個實踐的重點是把你在前端練級攻略第部分中學(xué)到的一些東西和結(jié)合起來。一旦你進(jìn)入框架部分,你將更好地理解并使用它們。到目前為止,你一直在使用進(jìn)行操作。它是在前端系統(tǒng)像今天這樣復(fù)雜之前編寫的。 本文是 前端練級攻略 第二部分,第一部分請看下面: 前端練級攻略(第一部分) 在第二部分,我們將重點學(xué)習(xí) JavaScript 作為一種獨立的語言,如...

    BWrong 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評論0 收藏0

發(fā)表評論

0條評論

chaosx110

|高級講師

TA的文章

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