參考
設(shè)計(jì)模式讀書(shū)筆記-----組合模式
C++設(shè)計(jì)模式——組合模式
Javascript設(shè)計(jì)模式理論與實(shí)戰(zhàn):組合模式
我們平時(shí)開(kāi)發(fā)過(guò)程中,一定會(huì)遇到這種情況:同時(shí)處理簡(jiǎn)單對(duì)象和由簡(jiǎn)單對(duì)象組成的復(fù)雜對(duì)象,這些簡(jiǎn)單對(duì)象和復(fù)雜對(duì)象會(huì)組合成樹(shù)形結(jié)構(gòu),在客戶端對(duì)其處理的時(shí)候要保持一致性。比如電商網(wǎng)站中的產(chǎn)品訂單梦鉴,每一張產(chǎn)品訂單可能有多個(gè)子訂單組合闺鲸,比如操作系統(tǒng)的文件夾,每個(gè)文件夾有多個(gè)子文件夾或文件维雇,我們作為用戶對(duì)其進(jìn)行復(fù)制,刪除等操作時(shí)晒他,不管是文件夾還是文件吱型,對(duì)我們操作者來(lái)說(shuō)是一樣的。在這種場(chǎng)景下陨仅,就非常適合使用組合模式來(lái)實(shí)現(xiàn)津滞。
一、基本知識(shí)
組合模式:將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)灼伤,組合模式使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性触徐。
組合模式主要有三個(gè)角色:
(1)抽象組件(Component):抽象類,主要定義了參與組合的對(duì)象的公共接口
(2)子對(duì)象(Leaf):組成組合對(duì)象的最基本對(duì)象
(3)組合對(duì)象(Composite):由子對(duì)象組合起來(lái)的復(fù)雜對(duì)象
理解組合模式的關(guān)鍵是要理解組合模式對(duì)單個(gè)對(duì)象和組合對(duì)象使用的一致性狐赡,我們接下來(lái)說(shuō)說(shuō)組合模式的實(shí)現(xiàn)加深理解撞鹉。
二、文件夾和文件的例子
//文件類:File.java
public abstract class File {
String name;
public File(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void display();
}
//文件夾類:Folder.java,該類包含對(duì)文件的增加鸟雏、刪除和瀏覽三個(gè)方法
public class Folder extends File{
private List<File> files;
public Folder(String name){
super(name);
files = new ArrayList<File>();
}
/**
* 瀏覽文件夾中的文件
*/
public void display() {
for(File file : files){
file.display();
}
}
/**
* @desc 向文件夾中添加文件
* @param file
* @return void
*/
public void add(File file){
files.add(file);
}
/**
* @desc 從文件夾中刪除文件
* @param file
* @return void
*/
public void remove(File file){
files.remove(file);
}
}
//然后是三個(gè)文件類:TextFile.java享郊、ImageFile.java、VideoFile.java
public class TextFile extends File{
public TextFile(String name) {
super(name);
}
public void display() {
System.out.println("這是文本文件孝鹊,文件名:" + super.getName());
}
}
public class ImagerFile extends File{
public ImagerFile(String name) {
super(name);
}
public void display() {
System.out.println("這是圖像文件炊琉,文件名:" + super.getName());
}
}
public class VideoFile extends File{
public VideoFile(String name) {
super(name);
}
public void display() {
System.out.println("這是影像文件,文件名:" + super.getName());
}
}
//最后是客戶端
public class Client {
public static void main(String[] args) {
/**
* 我們先建立一個(gè)這樣的文件系統(tǒng)
* 總文件
*
* a.txt b.jpg c文件夾
* c_1.text c_1.rmvb c_1.jpg
*
*/
//總文件夾
Folder zwjj = new Folder("總文件夾");
//向總文件夾中放入三個(gè)文件:1.txt又活、2.jpg苔咪、1文件夾
TextFile aText= new TextFile("a.txt");
ImagerFile bImager = new ImagerFile("b.jpg");
Folder cFolder = new Folder("C文件夾");
zwjj.add(aText);
zwjj.add(bImager);
zwjj.add(cFolder);
//向C文件夾中添加文件:c_1.txt、c_1.rmvb柳骄、c_1.jpg
TextFile cText = new TextFile("c_1.txt");
ImagerFile cImage = new ImagerFile("c_1.jpg");
VideoFile cVideo = new VideoFile("c_1.rmvb");
cFolder.add(cText);
cFolder.add(cImage);
cFolder.add(cVideo);
//遍歷C文件夾
cFolder.display();
//將c_1.txt刪除
cFolder.remove(cText);
System.out.println("-----------------------");
cFolder.display();
}
}
優(yōu)點(diǎn)
1悼泌、可以清楚地定義分層次的復(fù)雜對(duì)象,表示對(duì)象的全部或部分層次夹界,使得增加新構(gòu)件也更容易馆里。
2、客戶端調(diào)用簡(jiǎn)單可柿,客戶端可以一致的使用組合結(jié)構(gòu)或其中單個(gè)對(duì)象鸠踪。
3、定義了包含葉子對(duì)象和容器對(duì)象的類層次結(jié)構(gòu)复斥,葉子對(duì)象可以被組合成更復(fù)雜的容器對(duì)象营密,而這個(gè)容器對(duì)象又可以被組合,這樣不斷遞歸下去目锭,可以形成復(fù)雜的樹(shù)形結(jié)構(gòu)评汰。
4、更容易在組合體內(nèi)加入對(duì)象構(gòu)件痢虹,客戶端不必因?yàn)榧尤肓诵碌膶?duì)象構(gòu)件而更改原有代碼被去。
缺點(diǎn)
1、使設(shè)計(jì)變得更加抽象奖唯,對(duì)象的業(yè)務(wù)規(guī)則如果很復(fù)雜惨缆,則實(shí)現(xiàn)組合模式具有很大挑戰(zhàn)性,而且不是所有的方法都與葉子對(duì)象子類都有關(guān)聯(lián)
**模式適用場(chǎng)景 **
1丰捷、需要表示一個(gè)對(duì)象整體或部分層次坯墨,在具有整體和部分的層次結(jié)構(gòu)中,希望通過(guò)一種方式忽略整體與部分的差異病往,可以一致地對(duì)待它們捣染。
2、讓客戶能夠忽略不同對(duì)象層次的變化停巷,客戶端可以針對(duì)抽象構(gòu)件編程耍攘,無(wú)須關(guān)心對(duì)象層次結(jié)構(gòu)的細(xì)節(jié)榕栏。
模式總結(jié)
1、 組合模式用于將多個(gè)對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“整體-部分”的結(jié)構(gòu)層次少漆。組合模式對(duì)單個(gè)對(duì)象(葉子對(duì)象)和組合對(duì)象(容器對(duì)象)的使用具有一致性臼膏。
2、 組合對(duì)象的關(guān)鍵在于它定義了一個(gè)抽象構(gòu)建類示损,它既可表示葉子對(duì)象渗磅,也可表示容器對(duì)象,客戶僅僅需要針對(duì)這個(gè)抽象構(gòu)建進(jìn)行編程检访,無(wú)須知道他是葉子對(duì)象還是容器對(duì)象始鱼,都是一致對(duì)待。
3脆贵、 組合模式雖然能夠非常好地處理層次結(jié)構(gòu)医清,也使得客戶端程序變得簡(jiǎn)單,但是它也使得設(shè)計(jì)變得更加抽象卖氨,而且也很難對(duì)容器中的構(gòu)件類型進(jìn)行限制会烙,這會(huì)導(dǎo)致在增加新的構(gòu)件時(shí)會(huì)產(chǎn)生一些問(wèn)題。