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

資訊專欄INFORMATION COLUMN

聽(tīng)飛狐聊JavaScript設(shè)計(jì)模式系列12

HitenDev / 1682人閱讀

摘要:,對(duì)組合對(duì)象執(zhí)行的操作可以向下傳遞到葉子節(jié)點(diǎn)進(jìn)行操作。組合模式之圖片庫(kù)圖片庫(kù)可以有選擇地隱藏或顯示圖片庫(kù)的全部或某一部分多帶帶的或是部分的。

本回內(nèi)容介紹

上一回,聊了橋接模式,做了一道計(jì)算題;介一回,聊組合模式(Composite),官方描述組合模式將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),組合模式使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。

組合模式特性

這里我理了一下,就組合模式的特性而言:
1,組合模式把對(duì)象分為組合對(duì)象和葉子對(duì)象兩種。
2,組合對(duì)象和葉子對(duì)象實(shí)現(xiàn)同一批操作。
3,對(duì)組合對(duì)象執(zhí)行的操作可以向下傳遞到葉子節(jié)點(diǎn)進(jìn)行操作。
這樣做帶來(lái)的好處
1,解耦,弱化類與類之間的耦合,同樣的方法得到抽離處理組合對(duì)象和葉子對(duì)象;
2,把對(duì)象組合成屬性結(jié)構(gòu)的對(duì)象。
這個(gè)也是我在網(wǎng)上看了很多描述后做的總結(jié)。這里先看一下,然后看例子,看完例子再來(lái)看總結(jié),應(yīng)該會(huì)更有心得,來(lái)吧,開(kāi)始咯。

1.組合模式

這里需要用到之前寫(xiě)過(guò)的接口類,不清楚的童鞋看看前面聊過(guò)的系列05,這里模擬一個(gè)導(dǎo)航菜單,如京東的一級(jí)導(dǎo)航,二級(jí)導(dǎo)航,三級(jí)導(dǎo)航,代碼如下:

var d = document;
// 定義組合接口
var CompositeInterface = new Interface("CompositeInterface",["addChild","getChild","href"]);
// 定義葉子接口
var LeafInterface = new Interface("LeafInterface",["href"]);
// 定義組合類,并定義名字,類型,子集
var Composite = function(name){
    this.name = name;
    this.type = "Composite";
    this.children = [];
}
// 組合類的方法實(shí)現(xiàn)
Composite.prototype = {
    // 之前說(shuō)過(guò)很多次的,還原指針
    constructor:Composite,
    // 添加子集
    addChild:function(child){
        this.children.push(child);
        return this;
    },
    // 獲取子集,這里是組合模式的關(guān)鍵
    getChild:function(name){
        // 定義一個(gè)結(jié)果數(shù)組
        var el = [];
        // 添加葉子對(duì)象的方法
        var addLeaf = function(item){
            // 判斷傳入的類型為組合對(duì)象的情況
            if(item.type==="Composite"){
                // 如果為組合對(duì)象說(shuō)明還有下一級(jí),則遞歸,還記得forEach函數(shù)吧,系列01講過(guò)的,不清楚的回過(guò)頭去看看再回憶一下,這里的arguments.callee是指向函數(shù)本身的指針
                item.children.forEach(arguments.callee);
            // 判斷如果為葉子對(duì)象,則直接添加到結(jié)果集
            }else if(item.type==="Leaf"){
                el.push(item);
            }        
        };
        // 判斷傳入的導(dǎo)航節(jié)點(diǎn)是否存在,并且是否等于當(dāng)前的節(jié)點(diǎn)
        if(name&&this.name!==name){
            // 遍歷沒(méi)什么好說(shuō)的
            this.children.forEach(function(item){
                // 判斷傳入節(jié)點(diǎn)為當(dāng)前節(jié)點(diǎn)并且為組合對(duì)象則遞歸
                if(item.name === name&&item.type === "Composite"){
                    item.children.forEach(addLeaf);
                }
                // 傳入的節(jié)點(diǎn)非當(dāng)前節(jié)點(diǎn)并且是組合對(duì)象則遞歸
                if(item.name !== name&&item.type === "Composite"){
                    item.children.forEach(arguments.callee);
                }
                // 傳入的類型如果是葉子對(duì)象,正好是調(diào)用的節(jié)點(diǎn),則直接添加到結(jié)果集
                if(item.name === name&&item.type === "Leaf"){
                    el.push(item);
                }
            });
        // 這里是不傳參,或者不等于當(dāng)前節(jié)點(diǎn)的情況
        }else{
            // 這里的遞歸同上
            this.children.forEach(addLeaf);
        }
        return el;
    },
    // 跳轉(zhuǎn)的方法
    href:function(name){
        // 獲取葉子對(duì)象
        var leaves = this.getChild(name);
        // 遍歷并執(zhí)行葉子對(duì)象的跳轉(zhuǎn)
        for(var i=0;i");
    }
};

代碼量太多,還是把測(cè)試部分代碼分開(kāi),如下:

// 以下是測(cè)試的代碼
var n1 = new Leaf("三級(jí)導(dǎo)航1");
var n2 = new Leaf("三級(jí)導(dǎo)航2");
var n3 = new Leaf("三級(jí)導(dǎo)航3");
var n4 = new Leaf("三級(jí)導(dǎo)航4");
var n5 = new Leaf("三級(jí)導(dǎo)航5");
var n6 = new Leaf("三級(jí)導(dǎo)航6");
// 寫(xiě)一個(gè)二級(jí)導(dǎo)航1,把前三個(gè)放入二級(jí)導(dǎo)航1
var nav1 = new Composite("二級(jí)導(dǎo)航1");
nav1.addChild(n1);
nav1.addChild(n2);
nav1.addChild(n3);
// 寫(xiě)一個(gè)二級(jí)導(dǎo)航2,把后三個(gè)放入二級(jí)導(dǎo)航2
var nav2 = new Composite("二級(jí)導(dǎo)航2");
nav2.addChild(n4);
nav2.addChild(n5);
nav2.addChild(n6);
// 寫(xiě)一個(gè)一級(jí)導(dǎo)航,把兩個(gè)二級(jí)導(dǎo)航放入一級(jí)導(dǎo)航
var nav = new Composite();
nav.addChild(nav1);
nav.addChild(nav2);
// 這里不傳則返回全部
nav.href("二級(jí)導(dǎo)航1");    // 返回三級(jí)導(dǎo)航1,三級(jí)導(dǎo)航2,三級(jí)導(dǎo)航3

作為第一個(gè)例子,為了便于大家理解,我基本把注釋都寫(xiě)完了,把一下葉子對(duì)象的方法省去了,只寫(xiě)了一個(gè)方法,更直觀方便理解。下一個(gè)例子用一個(gè)圖片庫(kù)來(lái)演示,走你。

2. 組合模式之圖片庫(kù)

圖片庫(kù)可以有選擇地隱藏或顯示圖片庫(kù)的全部或某一部分(多帶帶的或是部分的)。同上面一個(gè)例子一樣,一個(gè)組合類做庫(kù)、一個(gè)葉子類則是圖片本身,如下:

var d = document;
// 檢查組合對(duì)象Composite應(yīng)該具備的方法
var Composite     = new Interface("Composite",["add","remove","getChild"]);
// 檢查組合對(duì)象GalleryItem應(yīng)該具備的方法
var GalleryItem = new Interface("GalleryItem",["hide","show"]); 
// 實(shí)現(xiàn)Composite,GalleryItem組合對(duì)象類            
var DynamicGallery = function(id){             
    // 定義子集
    this.children = [];
    // 創(chuàng)建dom元素
    this.el       = d.createElement("div");
    // 這個(gè)id跟上面?zhèn)€例子的name是一樣的,傳入名
    this.el.id       = id;
    // 這個(gè)className跟上面例子的type是一樣的,區(qū)分層級(jí)
    this.el.className = "imageLib";
}
// 組合類的方法實(shí)現(xiàn)
DynamicGallery.prototype = {
    constructor:DynamicGallery,
    //  實(shí)現(xiàn)Composite組合對(duì)象接口
    add : function(child){
        // 檢測(cè)接口
        Interface.ensureImplements(child,Composite,GalleryItem);
        // 添加元素
        this.children.push(child);
        // 添加元素到末尾的方法appendChild,不清楚的童鞋在網(wǎng)上搜搜哈
        this.el.appendChild(child.getElement());
    },
    // 刪除節(jié)點(diǎn)
    remove : function(child){
        for(var node, i = 0; node = this.getChild(i); i++){
            // 這里判斷是否存在,存在則刪除
            if(node == child){
                // 這里用數(shù)組的方法splice,不清楚的童鞋網(wǎng)上搜搜,比較有意思的一個(gè)方法
                this.children.splice(i,1);
                break;
            }
        }
        // dom元素的刪除方法removeChild,不清楚的童鞋網(wǎng)上搜一下吧,嘿嘿~
        this.el.removeChild(child.getElement());
    },
    getChild : function(i){
        return this.children[i];
    },
    //  實(shí)現(xiàn)葉子對(duì)象
    hide : function(){
        for(var node, i = 0; node = this.getChild(i); i++){
            node.hide();
        }
        this.el.style.display = "none";
    },
    //  實(shí)現(xiàn)葉子對(duì)象
    show : function(){
        this.el.style.display = "block";
        for(var node, i = 0; node = this.getChild(i); i++){
            node.show();
        }
    },
    //  獲取當(dāng)前的節(jié)點(diǎn)
    getElement : function(){
        return this.el;
    }
}    
//  葉子類
var GalleryImage = function(src){
    this.el = document.createElement("img");
    this.el.className = "imageLeaf";
    this.el.src = src;
}
// 葉子類的方法實(shí)現(xiàn)
GalleryImage.prototype = {
    constructor:GalleryImage,
    // 這里的方法都是葉子對(duì)象的,已經(jīng)是葉子對(duì)象了,處于最底層的,沒(méi)有下一級(jí)了。上一個(gè)例子沒(méi)有寫(xiě),是因?yàn)楸M量少寫(xiě)代碼便于理解,這里我們不定義具體的實(shí)現(xiàn),直接拋出就好了
    add : function(){
        throw new Error("This is not a instance!");
    },
    remove : function(){
        throw new Error("This is not a instance!");
    },
    getChild : function(id){
        // 判斷是否是當(dāng)前元素,是則返回
        if(this.id = id){
            return this;
        }
        return null;
    },
 
    // 隱藏
    hide : function(){
        this.el.style.display = "none";
    },
    // 顯示
    show : function(){
        this.el.style.display = "block";
    },
    getElement : function(){
        return this.el;
    }
}

測(cè)試部分,代碼如下:

window.onload = function(){
    // 從這開(kāi)始是測(cè)試部分,組合類one,用one來(lái)表示層級(jí)最高吧
    var one = new DynamicGallery("one");
    // 這里可以循環(huán)多張圖片來(lái)測(cè)試,隨便搜點(diǎn)兒圖片做測(cè)試
    var item1 = new GalleryImage("./1.jpg");
    var item2 = new GalleryImage("./2.jpg");
    var item3 = new GalleryImage("./3.jpg");
    // 添加葉子對(duì)象到頂級(jí)組合類one
    one.add(item1);
    one.add(item2);
    one.add(item3);
    // 組合類two,層級(jí)次于one
    two = new DynamicGallery("two");
    // 同樣這里也可以循環(huán)多張圖片來(lái)測(cè)試
    var item4 = new GalleryImage("./4.jpg");
    var item5 = new GalleryImage("./5.jpg");
    var item6 = new GalleryImage("./6.jpg");
    two.add(item4);
    two.add(item5);
    two.add(item6);
    // 鏈?zhǔn)讲僮?,后面?huì)聊到
    d.getElementById("main").appendChild(one.getElement());
    one.add(two);
    one.show();
    // 這里寫(xiě)show,two里的圖片則顯示
    two.hide();
}

這個(gè)例子在網(wǎng)上很多,這里我改了下代碼,使組合對(duì)象和葉子對(duì)象更直觀,讓這兩個(gè)類來(lái)管理圖片庫(kù),代碼可以直接copy運(yùn)行。


裝個(gè)逼咯。雙12大超市小鋪?zhàn)佣荚诟慊顒?dòng),又是一陣買(mǎi)買(mǎi)買(mǎi)~~

這一回聊的組合模式,對(duì)于剛學(xué)JS面向?qū)ο蟮耐?,頗有難度,不過(guò)不要緊,困難像彈簧,你懂的呃(的呃要快速連讀^_^)~
下面的內(nèi)容,來(lái)聊聊遞歸,因?yàn)檫@回的組合模式用到了遞歸,剛好可以學(xué)習(xí)一下加深印象。

遞歸

官方概述程序調(diào)用自身的編程技巧稱為遞歸( recursion)。

// 經(jīng)典的累加,start簡(jiǎn)寫(xiě)s,end簡(jiǎn)寫(xiě)e,開(kāi)始和結(jié)束的數(shù)字
function add(s,e){
    // 初始化遍歷為number類型,默認(rèn)值0
    var num = 0;
    // 先加第一項(xiàng)
    num += s;
    // 判斷首項(xiàng)小于末項(xiàng)則執(zhí)行
    if(s

這里之所以用arguments.callee,好處就在于改變函數(shù)名的時(shí)候,不用再去該內(nèi)部的代碼,防止出錯(cuò)。

這一回,主要聊了組合模式,遞歸,其中組合模式還回憶了之前聊過(guò)的接口類,數(shù)組新特性forEach等,這回比較抽象,需要多理解~~
下一回,聊一聊狀態(tài)模式。

看完點(diǎn)個(gè)贊,推薦推薦咯,人氣+++,動(dòng)力才能+++吖,嘿嘿~~

注:此系飛狐原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處

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

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

相關(guān)文章

  • 聽(tīng)飛狐JavaScript設(shè)計(jì)模式系列06

    本回內(nèi)容介紹 上一回聊到JS中模擬接口,裝飾者模式,摻元類,分析了backbone的繼承源碼,感覺(jué)還好吧! 介一回,偶們來(lái)聊一下在JS單例模式(singleton),單例模式其實(shí)運(yùn)用很廣泛,比如:jquery,AngularJS,underscore吖蝦米的都是單例模式,來(lái)吧,直接開(kāi)始咯: 1. 單例模式 保證一個(gè)類只有一個(gè)實(shí)例,從全局命名空間里提供一個(gè)唯一的訪問(wèn)點(diǎn)來(lái)訪問(wèn)該對(duì)象。其實(shí)之前寫(xiě)過(guò)的對(duì)象...

    hiYoHoo 評(píng)論0 收藏0
  • 聽(tīng)飛狐JavaScript設(shè)計(jì)模式系列02

    摘要:本回內(nèi)容介紹上一回聊到數(shù)據(jù)類型,簡(jiǎn)單的過(guò)了一遍,包括個(gè)數(shù)組新特性等,這一回來(lái)聊聊對(duì)象,結(jié)合數(shù)組來(lái)實(shí)戰(zhàn)一些例子,在做題中成長(zhǎng),記憶會(huì)更深刻,來(lái)吧,開(kāi)始咯創(chuàng)建實(shí)例的方式有兩種使用操作符后跟構(gòu)造函數(shù)飛狐使用對(duì)象字面量表示法飛狐也可以飛狐這種寫(xiě)法與 本回內(nèi)容介紹 上一回聊到JS數(shù)據(jù)類型,簡(jiǎn)單的過(guò)了一遍,包括9個(gè)數(shù)組新特性等,這一回來(lái)聊聊Object對(duì)象,結(jié)合數(shù)組來(lái)實(shí)戰(zhàn)一些例子,在做題中成長(zhǎng),記...

    tangr206 評(píng)論0 收藏0
  • 聽(tīng)飛狐JavaScript設(shè)計(jì)模式系列11

    摘要:橋接模式之特權(quán)函數(shù)特權(quán)函數(shù),用一些具有特權(quán)的方法作為橋梁以便訪問(wèn)私有空間,可以回憶一下之前的系列。連續(xù)自然數(shù)分組,計(jì)算最多組的個(gè)數(shù)將至這個(gè)連續(xù)自然數(shù)分成組使每組相加的值相等。個(gè)數(shù)組中數(shù)字最多的一組有個(gè)此時(shí)的和為。 本回內(nèi)容介紹 上一回,聊了適配器模式,圖片預(yù)加載,介一回,聊橋接模式(Bridge),跟之前一樣,難度比較小,橋接模式將抽象部分與它的實(shí)現(xiàn)部分分離,通過(guò)橋接模式聯(lián)系彼此,同時(shí)...

    wanglu1209 評(píng)論0 收藏0
  • 聽(tīng)飛狐JavaScript設(shè)計(jì)模式系列10

    摘要:本回內(nèi)容介紹上一回,聊了代理模式,虛擬代理,圖片懶加載,介一回,也比較容易,適配器模式,用一個(gè)新的接口對(duì)現(xiàn)有類的接口進(jìn)行包裝,處理類與的不匹配。這一回,主要聊了適配器模式,圖片預(yù)加載,主要還是理解下一回,聊一聊橋接模式,順便做一做計(jì)算題。 本回內(nèi)容介紹 上一回,聊了代理模式,虛擬代理,圖片懶加載,介一回,也比較容易,適配器模式(Adapter),用一個(gè)新的接口對(duì)現(xiàn)有類的接口進(jìn)行包裝,處...

    yexiaobai 評(píng)論0 收藏0
  • 聽(tīng)飛狐JavaScript設(shè)計(jì)模式系列14

    摘要:本回內(nèi)容介紹上一回,聊了聊狀態(tài)模式,并介紹了一下介一回,聊鏈?zhǔn)骄幊?,模擬一下,再模擬一下封裝一個(gè)庫(kù)。這一回,主要聊了鏈?zhǔn)秸{(diào)用,模擬了,尤其是,希望大家能喜歡這次代碼分享。下一回,聊一聊的策略模式。 本回內(nèi)容介紹 上一回,聊了聊狀態(tài)模式(State),并介紹了一下vue.js;介一回,聊鏈?zhǔn)骄幊?,模擬一下jQuery,再模擬一下underscore.js,封裝一個(gè)庫(kù)。 1. 鏈?zhǔn)秸{(diào)用 (...

    fox_soyoung 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<