JavaScript 設(shè)計(jì)模式之組合模式解析
更新時(shí)間:2010年04月09日 11:07:37 作者:
“組合模式”顧名思意就是將多種實(shí)現(xiàn)組合在一起而達(dá)到牽一處而動(dòng)全身的效果。
怎么說(shuō)呢?!就像是動(dòng)物(組合對(duì)象)一樣,當(dāng)它生下后代(葉對(duì)象)時(shí),它的后代就有了某種功能(比如:挖洞,聽(tīng)力好等等);也像是一棵樹(shù),它有一個(gè)根(組合對(duì)象)然后是從這個(gè)棵樹(shù)向外冒出的其他枝桿(組合對(duì)象)以及從這些枝桿又向外長(zhǎng)的葉子(葉對(duì)象)。換句話(huà)說(shuō),就是當(dāng)祖先已經(jīng)有了,那么只要從這個(gè)祖先衍生出來(lái)的其他孩子(包括這個(gè)祖先下的其他組合對(duì)象)已經(jīng)就具備了某種功能,看上去貌似又有些像是繼承?!敖M合模式”在組合對(duì)象的層次體系中有兩種類(lèi)型的對(duì)象:葉對(duì)象和組合對(duì)象。組合模式擅長(zhǎng)于對(duì)大批對(duì)象進(jìn)行操作。
“組合模式”就是在做一個(gè)項(xiàng)目的時(shí)候,我們要把在這個(gè)項(xiàng)目中即將出現(xiàn)的方法都在組合對(duì)象中定義(包括葉對(duì)象中的方法),而它們的葉對(duì)象將會(huì)繼承組合對(duì)象。當(dāng)組合對(duì)象被實(shí)例化后其葉對(duì)象的方法也相應(yīng)地被實(shí)例化了。可能我說(shuō)的有些亂,下面就用一個(gè)例子來(lái)說(shuō)明吧。
“組合模式”是一種專(zhuān)為創(chuàng)建Web上的動(dòng)態(tài)用戶(hù)界面而量身定制的模式。使用這種模式,可以用一條命令在多個(gè)對(duì)象上激發(fā)復(fù)雜的或遞歸的行為。
使用“組合模式”可以為我們帶來(lái)兩大好處:
1、可以用同樣的方法處理對(duì)象的集合與其中的特定子對(duì)象。
2、可以用來(lái)把一批子對(duì)象組織成樹(shù)形結(jié)構(gòu),并且使整棵樹(shù)都可以被遍歷。
只有同時(shí)具備以下兩個(gè)條件進(jìn)才適合使用組合模式:
1、存在一批組織成某處層次體系的對(duì)象(具體結(jié)構(gòu)可能在開(kāi)發(fā)期間無(wú)法知道)。
2、希望對(duì)這批對(duì)象或其中的一部分對(duì)象實(shí)話(huà)一個(gè)操作。
下面看一下示例:
具體要求是做一個(gè)圖片庫(kù)且可以有選擇地隱藏或顯示圖片庫(kù)的特定部分。這可能是單獨(dú)圖片,也可能是圖片庫(kù)。現(xiàn)在就需要兩個(gè)類(lèi)來(lái)完成這個(gè)功能:用作圖片庫(kù)的組合對(duì)象類(lèi)和用于圖片本身的葉對(duì)象類(lèi),代碼如下:
在上面的代碼中,首先定義的是組合對(duì)象類(lèi)和葉對(duì)象類(lèi)應(yīng)該實(shí)現(xiàn)的接口。除了常規(guī)的組合遠(yuǎn)景一分錢(qián)上,這些類(lèi)要怕硬欺軟 操作只包括hide和show。接下來(lái)我們定義葉對(duì)象。葉對(duì)象實(shí)現(xiàn)hide和show,代碼如下:
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']); // 檢查組合對(duì)象Composite應(yīng)該具備的方法
var GalleryItem = new Interface('GalleryItem', ['hide', 'show']); // 檢查組合對(duì)象GalleryItem應(yīng)該具備的方法
// DynamicGallery Class
var DynamicGallery = function(id){ // 實(shí)現(xiàn)Composite,GalleryItem組合對(duì)象類(lèi)
this.children = [];
this.element = document.createElement('div');
this.element.id = id;
this.element.className = 'dynamic-gallery';
}
DynamicGallery.prototype = {
// 實(shí)現(xiàn)Composite組合對(duì)象接口
add : function(child){
Interface.ensureImplements(child, Composite, DynamicGallery);
this.children.push(child);
this.element.appendChild(child.getElement());
},
remove : function(child){
for(var node, i = 0; node = this.getChild(i); i++){
if(node == child){
this.children.splice(i, 1);
break;
}
}
this.element.removeChild(child.getElement());
},
getChild : function(i){
return this.children[i];
},
// 實(shí)現(xiàn)DynamicGallery組合對(duì)象接口
hide : function(){
for(var node, i = 0; node = this.getChild(i); i++){
node.hide();
}
this.element.style.display = 'none';
},
show : functioln(){
this.element.style.display = 'block';
for(var node, i = 0; node = getChild(i); i++){
node.show();
}
},
// 幫助方法
getElement : function(){
return this.element;
}
}
以下是設(shè)置葉對(duì)象的相應(yīng)方法:
// GalleryImage class
var GalleryImage = function(src){ // 實(shí)現(xiàn)Composite和GalleryItem組合對(duì)象中所定義的方法
this.element = document.createElement('img');
this.element.className = 'gallery-image';
this.element.src = src;
}
GalleryImage.prototype = {
// 實(shí)現(xiàn)Composite接口
// 這些是葉結(jié)點(diǎn),所以我們不用實(shí)現(xiàn)這些方法,我們只需要定義即可
add : function(){},
remove : function(){},
getChild : function(){},
// 實(shí)現(xiàn)GalleryItem接口
hide : function(){
this.element.style.display = 'none';
},
show : function(){
this.element.style.display = '';
},
// 幫助方法
getElement : function(){
return this.element;
}
}
這是一個(gè)演示組合模式的工作方式的例子。每個(gè)類(lèi)都很簡(jiǎn)單,但由于有了這樣一種層次體系,我們就可以執(zhí)行一些復(fù)雜操作。GalleryImage類(lèi)的構(gòu)造函數(shù)會(huì)創(chuàng)建一個(gè)image元素。這個(gè)類(lèi)定義中的其余部分由空的組合對(duì)象方法(因?yàn)檫@是葉結(jié)點(diǎn))和GalleryItem要求的操作組成?,F(xiàn)在我們可以使用這兩個(gè)類(lèi)來(lái)管理圖片:
var topGallery = new DynamicGallery('top-gallery');
topGallery.add(new GalleryImage('/img/image-1.jpg'));
topGallery.add(new GalleryImage('/img/image-2.jpg'));
topGallery.add(new GalleryImage('/img/image-3.jpg'));
var vacationPhotos = new DyamicGallery('vacation-photos');
for(var i = 0, i < 30; i++){
vacationPhotos.add(new GalleryImage('/img/vac/image-' + i + '.jpg'));
}
topGallery.add(vacationPhotos);
topGallery.show();
vacationPhotos.hide();
組合模式之利,使用組合模式,簡(jiǎn)單的操作也能產(chǎn)生復(fù)雜的結(jié)果。不必編寫(xiě)大師手工遍歷數(shù)組或其他數(shù)據(jù)結(jié)構(gòu)的粘合代碼,只需對(duì)最頂層的對(duì)象執(zhí)行操作,主每一個(gè)子對(duì)象自己傳遞這個(gè)操作即可。這對(duì)于那些再三執(zhí)行的操作尤其有用。在組合模式中,各個(gè)對(duì)象之間的耦合非常松散。每當(dāng)對(duì)頂層組合對(duì)象執(zhí)行一個(gè)操作時(shí),實(shí)際上是在對(duì)整個(gè)結(jié)構(gòu)進(jìn)行嘗試優(yōu)先的搜索以查找節(jié)點(diǎn)。
組合模式之弊,由于對(duì)組合模式調(diào)用的任何操作都會(huì)被頗佳北至 它的所有子對(duì)象,如果這個(gè)層次體系很大的話(huà),系統(tǒng)的性能將會(huì)受到影響。
“組合模式”就是在做一個(gè)項(xiàng)目的時(shí)候,我們要把在這個(gè)項(xiàng)目中即將出現(xiàn)的方法都在組合對(duì)象中定義(包括葉對(duì)象中的方法),而它們的葉對(duì)象將會(huì)繼承組合對(duì)象。當(dāng)組合對(duì)象被實(shí)例化后其葉對(duì)象的方法也相應(yīng)地被實(shí)例化了。可能我說(shuō)的有些亂,下面就用一個(gè)例子來(lái)說(shuō)明吧。
“組合模式”是一種專(zhuān)為創(chuàng)建Web上的動(dòng)態(tài)用戶(hù)界面而量身定制的模式。使用這種模式,可以用一條命令在多個(gè)對(duì)象上激發(fā)復(fù)雜的或遞歸的行為。
使用“組合模式”可以為我們帶來(lái)兩大好處:
1、可以用同樣的方法處理對(duì)象的集合與其中的特定子對(duì)象。
2、可以用來(lái)把一批子對(duì)象組織成樹(shù)形結(jié)構(gòu),并且使整棵樹(shù)都可以被遍歷。
只有同時(shí)具備以下兩個(gè)條件進(jìn)才適合使用組合模式:
1、存在一批組織成某處層次體系的對(duì)象(具體結(jié)構(gòu)可能在開(kāi)發(fā)期間無(wú)法知道)。
2、希望對(duì)這批對(duì)象或其中的一部分對(duì)象實(shí)話(huà)一個(gè)操作。
下面看一下示例:
具體要求是做一個(gè)圖片庫(kù)且可以有選擇地隱藏或顯示圖片庫(kù)的特定部分。這可能是單獨(dú)圖片,也可能是圖片庫(kù)。現(xiàn)在就需要兩個(gè)類(lèi)來(lái)完成這個(gè)功能:用作圖片庫(kù)的組合對(duì)象類(lèi)和用于圖片本身的葉對(duì)象類(lèi),代碼如下:
在上面的代碼中,首先定義的是組合對(duì)象類(lèi)和葉對(duì)象類(lèi)應(yīng)該實(shí)現(xiàn)的接口。除了常規(guī)的組合遠(yuǎn)景一分錢(qián)上,這些類(lèi)要怕硬欺軟 操作只包括hide和show。接下來(lái)我們定義葉對(duì)象。葉對(duì)象實(shí)現(xiàn)hide和show,代碼如下:
復(fù)制代碼 代碼如下:
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']); // 檢查組合對(duì)象Composite應(yīng)該具備的方法
var GalleryItem = new Interface('GalleryItem', ['hide', 'show']); // 檢查組合對(duì)象GalleryItem應(yīng)該具備的方法
// DynamicGallery Class
var DynamicGallery = function(id){ // 實(shí)現(xiàn)Composite,GalleryItem組合對(duì)象類(lèi)
this.children = [];
this.element = document.createElement('div');
this.element.id = id;
this.element.className = 'dynamic-gallery';
}
DynamicGallery.prototype = {
// 實(shí)現(xiàn)Composite組合對(duì)象接口
add : function(child){
Interface.ensureImplements(child, Composite, DynamicGallery);
this.children.push(child);
this.element.appendChild(child.getElement());
},
remove : function(child){
for(var node, i = 0; node = this.getChild(i); i++){
if(node == child){
this.children.splice(i, 1);
break;
}
}
this.element.removeChild(child.getElement());
},
getChild : function(i){
return this.children[i];
},
// 實(shí)現(xiàn)DynamicGallery組合對(duì)象接口
hide : function(){
for(var node, i = 0; node = this.getChild(i); i++){
node.hide();
}
this.element.style.display = 'none';
},
show : functioln(){
this.element.style.display = 'block';
for(var node, i = 0; node = getChild(i); i++){
node.show();
}
},
// 幫助方法
getElement : function(){
return this.element;
}
}
以下是設(shè)置葉對(duì)象的相應(yīng)方法:
復(fù)制代碼 代碼如下:
// GalleryImage class
var GalleryImage = function(src){ // 實(shí)現(xiàn)Composite和GalleryItem組合對(duì)象中所定義的方法
this.element = document.createElement('img');
this.element.className = 'gallery-image';
this.element.src = src;
}
GalleryImage.prototype = {
// 實(shí)現(xiàn)Composite接口
// 這些是葉結(jié)點(diǎn),所以我們不用實(shí)現(xiàn)這些方法,我們只需要定義即可
add : function(){},
remove : function(){},
getChild : function(){},
// 實(shí)現(xiàn)GalleryItem接口
hide : function(){
this.element.style.display = 'none';
},
show : function(){
this.element.style.display = '';
},
// 幫助方法
getElement : function(){
return this.element;
}
}
這是一個(gè)演示組合模式的工作方式的例子。每個(gè)類(lèi)都很簡(jiǎn)單,但由于有了這樣一種層次體系,我們就可以執(zhí)行一些復(fù)雜操作。GalleryImage類(lèi)的構(gòu)造函數(shù)會(huì)創(chuàng)建一個(gè)image元素。這個(gè)類(lèi)定義中的其余部分由空的組合對(duì)象方法(因?yàn)檫@是葉結(jié)點(diǎn))和GalleryItem要求的操作組成?,F(xiàn)在我們可以使用這兩個(gè)類(lèi)來(lái)管理圖片:
復(fù)制代碼 代碼如下:
var topGallery = new DynamicGallery('top-gallery');
topGallery.add(new GalleryImage('/img/image-1.jpg'));
topGallery.add(new GalleryImage('/img/image-2.jpg'));
topGallery.add(new GalleryImage('/img/image-3.jpg'));
var vacationPhotos = new DyamicGallery('vacation-photos');
for(var i = 0, i < 30; i++){
vacationPhotos.add(new GalleryImage('/img/vac/image-' + i + '.jpg'));
}
topGallery.add(vacationPhotos);
topGallery.show();
vacationPhotos.hide();
組合模式之利,使用組合模式,簡(jiǎn)單的操作也能產(chǎn)生復(fù)雜的結(jié)果。不必編寫(xiě)大師手工遍歷數(shù)組或其他數(shù)據(jù)結(jié)構(gòu)的粘合代碼,只需對(duì)最頂層的對(duì)象執(zhí)行操作,主每一個(gè)子對(duì)象自己傳遞這個(gè)操作即可。這對(duì)于那些再三執(zhí)行的操作尤其有用。在組合模式中,各個(gè)對(duì)象之間的耦合非常松散。每當(dāng)對(duì)頂層組合對(duì)象執(zhí)行一個(gè)操作時(shí),實(shí)際上是在對(duì)整個(gè)結(jié)構(gòu)進(jìn)行嘗試優(yōu)先的搜索以查找節(jié)點(diǎn)。
組合模式之弊,由于對(duì)組合模式調(diào)用的任何操作都會(huì)被頗佳北至 它的所有子對(duì)象,如果這個(gè)層次體系很大的話(huà),系統(tǒng)的性能將會(huì)受到影響。
您可能感興趣的文章:
- 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組合模式學(xué)習(xí)要點(diǎn)
- 設(shè)計(jì)模式中的組合模式在JavaScript程序構(gòu)建中的使用
- javascript設(shè)計(jì)模式 – 組合模式原理與應(yīng)用實(shí)例分析
- JavaScript設(shè)計(jì)模式開(kāi)發(fā)中組合模式的使用教程
- javascript適配器模式和組合模式原理與實(shí)現(xiàn)方法詳解
相關(guān)文章
JavaScript 繼承機(jī)制的實(shí)現(xiàn)(待續(xù))
JavaScript繼承機(jī)制的實(shí)現(xiàn),后期會(huì)有一些補(bǔ)充。2010-05-05javascript實(shí)現(xiàn)面向?qū)ο箢?lèi)的功能書(shū)寫(xiě)技巧
經(jīng)過(guò)前段時(shí)間,學(xué)習(xí)《ajax完全自學(xué)手冊(cè)》后,才知道javascript原來(lái)還可以這么寫(xiě)。2010-03-03JavaScript 設(shè)計(jì)模式 安全沙箱模式
沙箱模式常見(jiàn)于YUI3 core,它是一種采用同一構(gòu)造器(Constructor)生成彼此獨(dú)立且互不干擾(self-contained)的實(shí)例對(duì)象,而從避免污染全局對(duì)象的方法2010-09-09JavaScript 三種創(chuàng)建對(duì)象的方法
JavaScript中對(duì)象的創(chuàng)建有以下幾種方式 使用內(nèi)置對(duì)象 使用JSON符號(hào) 自定義對(duì)象構(gòu)造。大家可以參考下。2009-10-10JavaScript面象對(duì)象設(shè)計(jì)
學(xué)習(xí)js的高境界就是使用面向?qū)ο蟮姆椒ǎ瑢?shí)現(xiàn)js的調(diào)用2008-04-04Javascript面向?qū)ο髷U(kuò)展庫(kù)代碼分享
最近一直在用js做項(xiàng)目,遇到了許多需要應(yīng)用面向?qū)ο髞?lái)設(shè)計(jì)的功能,由于js對(duì)OOP的原生支持還不是很完善,所以就寫(xiě)了一個(gè)面向?qū)ο蟮臄U(kuò)展庫(kù)用做底層支持,現(xiàn)在把它單獨(dú)整理出來(lái),完善了一些功能,在這里分享一下2012-03-03