-
組合模式
鎖定
組合模式,將對象組合成樹形結構以表示“部分-整體”的層次結構。
- 中文名
- 組合模式
- 外文名
- Composite Pattern
- 適用性
- 想表示對象的部分-整體層次結構
- 類 別
- 軟件設計模式
組合模式組合模式概述
組合模式(Composite Pattern)
組合模式使得用户對單個對象和組合對象的使用具有一致性。
有時候又叫做部分-整體模式,它使我們樹型結構的問題中,模糊了簡單元素和複雜元素的概念,客户程序可以像處理簡單元素一樣來處理複雜元素,從而使得客户程序與複雜元素的內部結構解耦。
組合模式讓你可以優化處理遞歸或分級數據結構。有許多關於分級數據結構的例子,使得組合模式非常有用武之地。關於分級數據結構的一個普遍性的例子是你每次使用電腦時所遇到的:文件系統。文件系統由目錄和文件組成。每個目錄都可以裝內容。目錄的內容可以是文件,也可以是目錄。按照這種方式,計算機的文件系統就是以遞歸結構來組織的。如果你想要描述這樣的數據結構,那麼你可以使用組合模式Composite。
定義
(GoF《設計模式》):將對象組合成樹形結構以表示“部分整體”的層次結構。組合模式使得用户對單個對象和組合對象的使用具有一致性。
涉及角色:
1.Component 是組合中的對象聲明接口,在適當的情況下,實現所有類共有接口的默認行為。聲明一個接口用於訪問和管理Component子部件。
2.Leaf 在組合中表示葉子結點對象,葉子結點沒有子結點。
3.Composite 定義有枝節點行為,用來存儲子部件,在Component接口中實現與子部件有關操作,如增加(add)和刪除(remove)等。
適用性
以下情況下適用Composite模式:
1.你想表示對象的部分-整體層次結構
2.你希望用户忽略組合對象與單個對象的不同,用户將統一地使用組合結構中的所有對象。
組合模式總結
組合模式解耦了客户程序與複雜元素內部結構,從而使客户程序可以像處理簡單元素一樣來處理複雜元素。
如果你想要創建層次結構,並可以在其中以相同的方式對待所有元素,那麼組合模式就是最理想的選擇。本章使用了一個文件系統的例子來舉例説明了組合模式的用途。在這個例子中,文件和目錄都執行相同的接口,這是組合模式的關鍵。通過執行相同的接口,你就可以用相同的方式對待文件和目錄,從而實現將文件或者目錄儲存為目錄的子級元素。
組合模式示例
基於Java的樣例:
比如現實中公司內各部門的層級關係
抽象接口類:
package com.zyh.designpattern.composite; public abstract class Company { private String name; public Company(String name) { super(); this.name = name; } public Company(){} public String getName() { return name; } public void setName(String name) { this.name = name; } protected abstract void add(Company company); protected abstract void remove(Company company); protected abstract void display(int depth); }
枝結點類:
package com.zyh.designpattern.composite; import java.util.ArrayList; import java.util.List; public class ConcreteCompany extends Company { private List<Company> cList; public ConcreteCompany() { cList = new ArrayList(); } public ConcreteCompany(String name) { super(name); cList = new ArrayList(); } @Override protected void add(Company company) { cList.add(company); } @Override protected void display(int depth) { StringBuilder sb = new StringBuilder(""); for (int i = 0; i < depth; i++) { sb.append("-"); } System.out.println(new String(sb) + this.getName()); for (Company c : cList) { c.display(depth + 2); } } @Override protected void remove(Company company) { cList.remove(company); } }
兩個葉結點類:
-------------------------1---------------------------.
package com.zyh.designpattern.composite; public class HRDepartment extends Company { public HRDepartment(String name) { super(name); } @Override protected void add(Company company) { } @Override protected void display(int depth) { StringBuilder sb = new StringBuilder(""); for (int i = 0; i < depth; i++) { sb.append("-"); } System.out.println(new String(sb) + this.getName()); } @Override protected void remove(Company company) { } }
----------------2-------------------
package com.zyh.designpattern.composite; public class FinanceDepartment extends Company { public FinanceDepartment(String name) { super(name); } @Override protected void add(Company company) { } @Override protected void display(int depth) { StringBuilder sb = new StringBuilder(""); for (int i = 0; i < depth; i++) { sb.append("-"); } System.out.println(new String(sb) + this.getName()); } @Override protected void remove(Company company) { } }
客户端:
package com.zyh.designpattern.composite; public class Client { public static void main(String[] args) { Company root = new ConcreteCompany(); root.setName("北京總公司"); root.add(new HRDepartment("總公司人力資源部")); root.add(new FinanceDepartment("總公司財務部")); Company shandongCom = new ConcreteCompany("山東分公司"); shandongCom.add(new HRDepartment("山東分公司人力資源部")); shandongCom.add(new FinanceDepartment("山東分公司賬務部")); Company zaozhuangCom = new ConcreteCompany("棗莊辦事處"); zaozhuangCom.add(new FinanceDepartment("棗莊辦事處財務部")); zaozhuangCom.add(new HRDepartment("棗莊辦事處人力資源部")); Company jinanCom = new ConcreteCompany("濟南辦事處"); jinanCom.add(new FinanceDepartment("濟南辦事處財務部")); jinanCom.add(new HRDepartment("濟南辦事處人力資源部")); shandongCom.add(jinanCom); shandongCom.add(zaozhuangCom); Company huadongCom = new ConcreteCompany("上海華東分公司"); huadongCom.add(new HRDepartment("上海華東分公司人力資源部")); huadongCom.add(new FinanceDepartment("上海華東分公司賬務部")); Company hangzhouCom = new ConcreteCompany("杭州辦事處"); hangzhouCom.add(new FinanceDepartment("杭州辦事處財務部")); hangzhouCom.add(new HRDepartment("杭州辦事處人力資源部")); Company nanjingCom = new ConcreteCompany("南京辦事處"); nanjingCom.add(new FinanceDepartment("南京辦事處財務部")); nanjingCom.add(new HRDepartment("南京辦事處人力資源部")); huadongCom.add(hangzhouCom); huadongCom.add(nanjingCom); root.add(shandongCom); root.add(huadongCom); root.display(0); } }
基於C++的樣例:
#include <string> class Menu { public: virtual ~Menu(); virtual void Add(Menu*); virtual void Remove(Menu*); virtual Menu* GetChild(int); virtual void Display() = 0; protected: Menu(); Menu(std::string); std::string m_strName; }; //Menu.cpp #include "stdafx.h" #include "Menu.h" Menu::Menu() { } Menu::Menu(std::string strName) : m_strName(strName) { } Menu::~Menu() { } void Menu::Add(Menu* pMenu) {} void Menu::Remove(Menu* pMenu) {} Menu* Menu::GetChild(int index) { return NULL; } //SubMenu.h #include "Menu.h" class SubMenu : public Menu { public: SubMenu(); SubMenu(std::string); virtual ~SubMenu(); void Display(); }; //SubMenu.cpp #include "stdafx.h" #include "SubMenu.h" #include <iostream> using namespace std; SubMenu::SubMenu() { } SubMenu::SubMenu(string strName) : Menu(strName) { } SubMenu::~SubMenu() { } void SubMenu::Display() { cout << m_strName << endl; } //CompositMenu.h #include "Menu.h" #include <vector> class CompositMenu : public Menu { public: CompositMenu(); CompositMenu(std::string); virtual ~CompositMenu(); void Add(Menu*); void Remove(Menu*); Menu* GetChild(int); void Display(); private: std::vector<Menu*> m_vMenu; }; //CompositMenu.cpp #include "stdafx.h" #include "CompositMenu.h" #include <iostream> using namespace std; CompositMenu::CompositMenu() { } CompositMenu::CompositMenu(string strName) : Menu(strName) { } CompositMenu::~CompositMenu() { } void CompositMenu::Add(Menu* pMenu) { m_vMenu.push_back(pMenu); } void CompositMenu::Remove(Menu* pMenu) { m_vMenu.erase(&pMenu); } Menu* CompositMenu::GetChild(int index) { return m_vMenu[index]; } void CompositMenu::Display() { cout << "+" << m_strName << endl; vector<Menu*>::iterator it = m_vMenu.begin(); for (; it != m_vMenu.end(); ++it) { cout << "|-"; (*it)->Display(); } } #include "stdafx.h" #include "Menu.h" #include "SubMenu.h" #include "CompositMenu.h" int main(int argc, char* argv[]) { Menu* pMenu = new CompositMenu("國內新聞"); pMenu->Add(new SubMenu("時事新聞")); pMenu->Add(new SubMenu("社會新聞")); pMenu->Display(); pMenu = new CompositMenu("國際新聞"); pMenu->Add(new SubMenu("國際要聞")); pMenu->Add(new SubMenu("環球視野")); pMenu->Display(); return 0; }
- 參考資料
-
- 1. 我所理解的設計模式(C++實現)——組合模式(Composite Pattern) .CSDN.NET[引用日期2013-04-23]