設(shè)計(jì)模式中的組合模式在JavaScript程序構(gòu)建中的使用
定義
組合,顧名思義是指用包含多個(gè)部件的對(duì)象創(chuàng)建單一實(shí)體。 這個(gè)單一實(shí)體將用作所有這些部件的訪問點(diǎn),雖然這大大簡(jiǎn)化了操作,但也可能具有相當(dāng)?shù)钠垓_性,因?yàn)闆]有哪種隱性方式明確表明該組合包含多少部件。
組合模式的目標(biāo)是解耦客戶程序與復(fù)雜元素內(nèi)部架構(gòu),使得客戶程序?qū)Υ凶釉囟家灰曂省?/p>
每個(gè)子節(jié)點(diǎn)都可以使復(fù)雜的存在,對(duì)于父節(jié)點(diǎn)來說,不需要知道子節(jié)點(diǎn)的復(fù)雜性或者實(shí)現(xiàn)子節(jié)點(diǎn)的復(fù)雜性,只需要關(guān)注子節(jié)點(diǎn)的特定方法,便可以使用子節(jié)點(diǎn)。簡(jiǎn)化了父和子之間的關(guān)系。
對(duì)于子節(jié)點(diǎn)來說也是一樣的,過多的接口暴露有時(shí)候也是一種濫用,同時(shí)也減少了對(duì)外部的依賴。
示例
我們最好使用例證解說組合。 在下圖中,您可以看到兩種不同類型的對(duì)象: 容器和庫是組合,圖像是葉片。 組合可承載子項(xiàng),但一般不會(huì)實(shí)施更多行為。 葉片包含絕大多數(shù)行為,但不能承載子項(xiàng),至少在傳統(tǒng)的組合示例中不可以。
此示例創(chuàng)建圖片庫,將其作為組合模式示例。 只有三個(gè)層次: 專輯、庫和圖像。 專輯和庫將作為組合,圖像是葉片,如上面那張圖所示。這是一種比組合本身需求更加明確的結(jié)構(gòu),但對(duì)于本示例而言,將這些層次僅限制為組合或葉片很有意義。 標(biāo)準(zhǔn)組合不會(huì)限制哪些結(jié)構(gòu)層次可以具有葉片,也不會(huì)限制葉片數(shù)量。
要開始操作,應(yīng)首先創(chuàng)建用于專輯和庫的 GalleryComposite“類”。 請(qǐng)注意,我正在使用 jQuery 執(zhí)行 DOM 操作以簡(jiǎn)化過程。
var GalleryComposite = function (heading, id) { this.children = []; this.element = $('<div id="' + id + '" class="composite-gallery"></div>') .append('<h2>' + heading + '</h2>'); } GalleryComposite.prototype = { add: function (child) { this.children.push(child); this.element.append(child.getElement()); }, remove: function (child) { for (var node, i = 0; node = this.getChild(i); i++) { if (node == child) { this.children.splice(i, 1); this.element.detach(child.getElement()); return true; } if (node.remove(child)) { return true; } } return false; }, getChild: function (i) { return this.children[i]; }, hide: function () { for (var node, i = 0; node = this.getChild(i); i++) { node.hide(); } this.element.hide(0); }, show: function () { for (var node, i = 0; node = this.getChild(i); i++) { node.show(); } this.element.show(0); }, getElement: function () { return this.element; } }
這個(gè)位置有點(diǎn)棘手,能否允許我再更多的解釋一下? 我們同時(shí)使用 add, remove, 和getChild getChild 方法構(gòu)建這一組合。 本示例不會(huì)實(shí)際使用 remove 和 getChild,但它們對(duì)于創(chuàng)建動(dòng)態(tài)組合非常有用。 hide, show, 和getElement 方法則用來操縱 DOM。 該組合旨在作為庫的 表示在頁面上向用戶展示。 該組合可通過 hide 和 show控制這些庫元素。 如果在專輯上調(diào)用 hide,則整個(gè)專輯將消失,或者您也可以只在單一圖像上調(diào)用它,這樣只有該圖像會(huì)消失。
現(xiàn)在,創(chuàng)建一個(gè) GalleryImage類。 請(qǐng)注意,它使用的方法與 GalleryComposite完全相同。 換句話說,它們實(shí)現(xiàn)同一接口,不同的是該圖像是葉片,因此不會(huì)實(shí)際對(duì)子項(xiàng)相關(guān)方法執(zhí)行任何操作,就像不具有任何子項(xiàng)一樣。 必須使用同一接口運(yùn)行該組合,因?yàn)榻M合元素不知道自身添加的是另一個(gè)組合元素還是葉片,因此如果嘗試在其子項(xiàng)上調(diào)用這些方法,則需要運(yùn)行完全正常,沒有任何錯(cuò)誤。
var GalleryImage = function (src, id) { this.children = []; this.element = $('<img />') .attr('id', id) .attr('src', src); } GalleryImage.prototype = { // Due to this being a leaf, it doesn't use these methods, // but must implement them to count as implementing the // Composite interface add: function () { }, remove: function () { }, getChild: function () { }, hide: function () { this.element.hide(0); }, show: function () { this.element.show(0); }, getElement: function () { return this.element; } }
鑒于您已經(jīng)構(gòu)建了對(duì)象原型,您現(xiàn)已能夠進(jìn)行使用。 從下面您可以看到實(shí)際構(gòu)建圖像庫的代碼。
var container = new GalleryComposite('', 'allgalleries'); var gallery1 = new GalleryComposite('Gallery 1', 'gallery1'); var gallery2 = new GalleryComposite('Gallery 2', 'gallery2'); var image1 = new GalleryImage('image1.jpg', 'img1'); var image2 = new GalleryImage('image2.jpg', 'img2'); var image3 = new GalleryImage('image3.jpg', 'img3'); var image4 = new GalleryImage('image4.jpg', 'img4'); gallery1.add(image1); gallery1.add(image2); gallery2.add(image3); gallery2.add(image4); container.add(gallery1); container.add(gallery2); // Make sure to add the top container to the body, // otherwise it'll never show up. container.getElement().appendTo('body'); container.show();
組合模式之利:
簡(jiǎn)單的操作也能產(chǎn)生復(fù)雜的結(jié)果,只需對(duì)最頂層的對(duì)象執(zhí)行操作,讓每一個(gè)子對(duì)象自己傳遞這個(gè)操作即可。這對(duì)于那些再三執(zhí)行的操作尤其有用。
在組合模式中,各個(gè)對(duì)象之間的耦合非常松散。只要它們實(shí)現(xiàn)了同樣的接口那么改變它們的位置或互換它們只是舉手之勞。著促進(jìn)了代碼的重用,也有利于代碼重構(gòu)。
每當(dāng)對(duì)頂層組合對(duì)象執(zhí)行一個(gè)操作時(shí),實(shí)際上是在對(duì)整個(gè)結(jié)構(gòu)進(jìn)行深度優(yōu)先的搜索以查找節(jié)點(diǎn),而創(chuàng)建組合對(duì)象的程序員對(duì)這些細(xì)節(jié)一無所知。在這個(gè)層次體系中添加、刪除和查找節(jié)點(diǎn)都非常容易。
組合模式之弊:
組合對(duì)象的易用性可能掩蓋了它所支持的每一種操作的代價(jià)。由于組合對(duì)象調(diào)用的任何操作都會(huì)被傳遞到它的所有子對(duì)象如果這個(gè)層次體系很大的話,系統(tǒng)的性能將會(huì)受到影響。組合模式的正常運(yùn)作需要用到某種形式的接口。
組合對(duì)象和節(jié)點(diǎn)類被用作HTML元素的包裝工具時(shí),組合對(duì)象必須遵守HTML的使用規(guī)則。例如,表格就很難轉(zhuǎn)化為一個(gè)組合對(duì)象。
接口檢查越嚴(yán)格,組合對(duì)象類也就越可靠。
- JavaScript適配器模式詳解
- javascript設(shè)計(jì)模式之Adapter模式【適配器模式】實(shí)現(xiàn)方法示例
- JavaScript設(shè)計(jì)模式之適配器模式介紹
- 深入理解JavaScript系列(39):設(shè)計(jì)模式之適配器模式詳解
- 詳解JavaScript實(shí)現(xiàn)設(shè)計(jì)模式中的適配器模式的方法
- javascript設(shè)計(jì)模式 – 適配器模式原理與應(yīng)用實(shí)例分析
- JavaScript設(shè)計(jì)模式學(xué)習(xí)之適配器模式
- JavaScript 設(shè)計(jì)模式之組合模式解析
- JavaScript組合模式學(xué)習(xí)要點(diǎn)
- javascript設(shè)計(jì)模式 – 組合模式原理與應(yīng)用實(shí)例分析
- JavaScript設(shè)計(jì)模式開發(fā)中組合模式的使用教程
- javascript適配器模式和組合模式原理與實(shí)現(xiàn)方法詳解
相關(guān)文章
在javaScript中關(guān)于submit和button的區(qū)別介紹
submit是button的一個(gè)特例,也是button的一種,它把提交這個(gè)動(dòng)作自動(dòng)集成了,submit和button,二者都以按鈕的形式展現(xiàn),看起來都是按鈕,所不同的是type屬性和處發(fā)響應(yīng)的事件上2013-10-10js修改地址欄URL參數(shù)解決url參數(shù)問題
現(xiàn)在做網(wǎng)頁,經(jīng)常會(huì)碰到處理地址欄參數(shù)的問題,因此,就專門做了一個(gè)修改地址欄參數(shù)的方法,需要了解的朋友可以參考下2012-12-12JavaScript字符串對(duì)象replace方法實(shí)例(用于字符串替換或正則替換)
這篇文章主要介紹了JavaScript字符串對(duì)象replace方法實(shí)例,replace方法用于字符串替換,同時(shí)支持正則表達(dá)式替換,需要的朋友可以參考下2014-10-10javascript定義變量時(shí)加var與不加var的區(qū)別
這篇文章主要介紹了javascript 變量中 var 與不加var的區(qū)別,需要的朋友可以參考下2014-12-12JavaScript DOM 學(xué)習(xí)第五章 表單簡(jiǎn)介
在這一章我主要介紹一些用來檢測(cè)用戶輸入的代碼,利用這些代碼,你也可以寫一些自己的檢測(cè)函數(shù)。2010-02-02JavaScript入門教程(8) Location地址對(duì)象
location 地址對(duì)象 它描述的是某一個(gè)窗口對(duì)象所打開的地址。要表示當(dāng)前窗口的地址,只需要使用“l(fā)ocation”就行了2009-01-01對(duì)Js OOP編程 創(chuàng)建對(duì)象的一些全面理解
下面小編就為大家?guī)硪黄獙?duì)Js OOP編程 創(chuàng)建對(duì)象的一些全面理解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07