參考
設(shè)計模式讀書筆記-----組合模式
C++設(shè)計模式——組合模式
Javascript設(shè)計模式理論與實戰(zhàn):組合模式
我們平時開發(fā)過程中,一定會遇到這種情況:同時處理簡單對象和由簡單對象組成的復雜對象,這些簡單對象和復雜對象會組合成樹形結(jié)構(gòu),在客戶端對其處理的時候要保持一致性。比如電商網(wǎng)站中的產(chǎn)品訂單,每一張產(chǎn)品訂單可能有多個子訂單組合,比如操作系統(tǒng)的文件夾,每個文件夾有多個子文件夾或文件,我們作為用戶對其進行復制,刪除等操作時,不管是文件夾還是文件,對我們操作者來說是一樣的。在這種場景下,就非常適合使用組合模式來實現(xiàn)。
一、基本知識
組合模式:將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),組合模式使得用戶對單個對象和組合對象的使用具有一致性。
組合模式主要有三個角色:
(1)抽象組件(Component):抽象類,主要定義了參與組合的對象的公共接口
(2)子對象(Leaf):組成組合對象的最基本對象
(3)組合對象(Composite):由子對象組合起來的復雜對象
理解組合模式的關(guān)鍵是要理解組合模式對單個對象和組合對象使用的一致性,我們接下來說說組合模式的實現(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,該類包含對文件的增加、刪除和瀏覽三個方法
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);
}
}
//然后是三個文件類: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) {
/**
* 我們先建立一個這樣的文件系統(tǒng)
* 總文件
*
* a.txt b.jpg c文件夾
* c_1.text c_1.rmvb c_1.jpg
*
*/
//總文件夾
Folder zwjj = new Folder("總文件夾");
//向總文件夾中放入三個文件: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)點
1、可以清楚地定義分層次的復雜對象,表示對象的全部或部分層次,使得增加新構(gòu)件也更容易。
2、客戶端調(diào)用簡單,客戶端可以一致的使用組合結(jié)構(gòu)或其中單個對象。
3、定義了包含葉子對象和容器對象的類層次結(jié)構(gòu),葉子對象可以被組合成更復雜的容器對象,而這個容器對象又可以被組合,這樣不斷遞歸下去,可以形成復雜的樹形結(jié)構(gòu)。
4、更容易在組合體內(nèi)加入對象構(gòu)件,客戶端不必因為加入了新的對象構(gòu)件而更改原有代碼。
缺點
1、使設(shè)計變得更加抽象,對象的業(yè)務(wù)規(guī)則如果很復雜,則實現(xiàn)組合模式具有很大挑戰(zhàn)性,而且不是所有的方法都與葉子對象子類都有關(guān)聯(lián)
**模式適用場景 **
1、需要表示一個對象整體或部分層次,在具有整體和部分的層次結(jié)構(gòu)中,希望通過一種方式忽略整體與部分的差異,可以一致地對待它們。
2、讓客戶能夠忽略不同對象層次的變化,客戶端可以針對抽象構(gòu)件編程,無須關(guān)心對象層次結(jié)構(gòu)的細節(jié)。
模式總結(jié)
1、 組合模式用于將多個對象組合成樹形結(jié)構(gòu)以表示“整體-部分”的結(jié)構(gòu)層次。組合模式對單個對象(葉子對象)和組合對象(容器對象)的使用具有一致性。
2、 組合對象的關(guān)鍵在于它定義了一個抽象構(gòu)建類,它既可表示葉子對象,也可表示容器對象,客戶僅僅需要針對這個抽象構(gòu)建進行編程,無須知道他是葉子對象還是容器對象,都是一致對待。
3、 組合模式雖然能夠非常好地處理層次結(jié)構(gòu),也使得客戶端程序變得簡單,但是它也使得設(shè)計變得更加抽象,而且也很難對容器中的構(gòu)件類型進行限制,這會導致在增加新的構(gòu)件時會產(chǎn)生一些問題。