上圖,是一個公司的組織結構圖,總部下面有多個子公司,同時總部也有各個部門,子公司下面有多個部門。若是對這樣的公司開發一個OA系統,做爲程序員的你,如何設計這個OA系統呢?先不說如何設計實現,接着往下看,看完了下面的內容,再回過頭來想怎麼設計這樣的OA系統。ios
在GOF的《設計模式:可複用面向對象軟件的基礎》一書中對組合模式是這樣說的:將對象組合成樹形結構以表示「部分-總體」的層次結構。組合(Composite)模式使得用戶對單個對象和組合對象的使用具備一致性。程序員
組合模式(Composite)將小對象組合成樹形結構,使用戶操做組合對象如同操做一個單個對象。組合模式定義了「部分-總體」的層次結構,基本對象能夠被組合成更大的對象,並且這種操做是可重複的,不斷重複下去就能夠獲得一個很是大的組合對象,但這些組合對象與基本對象擁有相同的接口,於是組合是透明的,用法徹底一致。設計模式
咱們這樣來簡單的理解組合模式,組合模式就是把一些現有的對象或者元素,通過組合後組成新的對象,新的對象提供內部方法,可讓咱們很方便的完成這些元素或者內部對象的訪問和操做。咱們也能夠把組合對象理解成一個容器,容器提供各類訪問其內部對象或者元素的API,咱們只須要使用這些方法就能夠操做它了。函數
Component:spa
Leaf:設計
Composite:3d
Client:code
經過Component接口操做組合部件的對象。對象
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 using namespace std; 5 // 抽象的部件類描述未來全部部件共有的行爲 6 class Component 7 { 8 public: 9 Component(string name) : m_strCompname(name){} 10 virtual ~Component(){} 11 virtual void Operation() = 0; 12 virtual void Add(Component *) = 0; 13 virtual void Remove(Component *) = 0; 14 virtual Component *GetChild(int) = 0; 15 virtual string GetName() 16 { 17 return m_strCompname; 18 } 19 virtual void Print() = 0; 20 protected: 21 string m_strCompname; 22 }; 23 class Leaf : public Component 24 { 25 public: 26 Leaf(string name) : Component(name) 27 {} 28 void Operation() 29 { 30 cout<<"I'm "<<m_strCompname<<endl; 31 } 32 void Add(Component *pComponent){} 33 void Remove(Component *pComponent){} 34 Component *GetChild(int index) 35 { 36 return NULL; 37 } 38 void Print(){} 39 }; 40 class Composite : public Component 41 { 42 public: 43 Composite(string name) : Component(name) 44 {} 45 ~Composite() 46 { 47 vector<Component *>::iterator it = m_vecComp.begin(); 48 while (it != m_vecComp.end()) 49 { 50 if (*it != NULL) 51 { 52 cout<<"----delete "<<(*it)->GetName()<<"----"<<endl; 53 delete *it; 54 *it = NULL; 55 } 56 m_vecComp.erase(it); 57 it = m_vecComp.begin(); 58 } 59 } 60 void Operation() 61 { 62 cout<<"I'm "<<m_strCompname<<endl; 63 } 64 void Add(Component *pComponent) 65 { 66 m_vecComp.push_back(pComponent); 67 } 68 void Remove(Component *pComponent) 69 { 70 for (vector<Component *>::iterator it = m_vecComp.begin(); it != m_vecComp.end(); ++it) 71 { 72 if ((*it)->GetName() == pComponent->GetName()) 73 { 74 if (*it != NULL) 75 { 76 delete *it; 77 *it = NULL; 78 } 79 m_vecComp.erase(it); 80 break; 81 } 82 } 83 } 84 Component *GetChild(int index) 85 { 86 if (index > m_vecComp.size()) 87 { 88 return NULL; 89 } 90 return m_vecComp[index - 1]; 91 } 92 void Print() 93 { 94 for (vector<Component *>::iterator it = m_vecComp.begin(); it != m_vecComp.end(); ++it) 95 { 96 cout<<(*it)->GetName()<<endl; 97 } 98 } 99 private: 100 vector<Component *> m_vecComp; 101 }; 102 int main(int argc, char *argv[]) 103 { 104 Component *pNode = new Composite("Beijing Head Office"); 105 Component *pNodeHr = new Leaf("Beijing Human Resources Department"); 106 Component *pSubNodeSh = new Composite("Shanghai Branch"); 107 Component *pSubNodeCd = new Composite("Chengdu Branch"); 108 Component *pSubNodeBt = new Composite("Baotou Branch"); 109 pNode->Add(pNodeHr); 110 pNode->Add(pSubNodeSh); 111 pNode->Add(pSubNodeCd); 112 pNode->Add(pSubNodeBt); 113 pNode->Print(); 114 Component *pSubNodeShHr = new Leaf("Shanghai Human Resources Department"); 115 Component *pSubNodeShCg = new Leaf("Shanghai Purchasing Department"); 116 Component *pSubNodeShXs = new Leaf("Shanghai Sales department"); 117 Component *pSubNodeShZb = new Leaf("Shanghai Quality supervision Department"); 118 pSubNodeSh->Add(pSubNodeShHr); 119 pSubNodeSh->Add(pSubNodeShCg); 120 pSubNodeSh->Add(pSubNodeShXs); 121 pSubNodeSh->Add(pSubNodeShZb); 122 pNode->Print(); 123 // 公司不景氣,須要關閉上海質量監督部門 124 pSubNodeSh->Remove(pSubNodeShZb); 125 if (pNode != NULL) 126 { 127 delete pNode; 128 pNode = NULL; 129 } 130 return 0; 131 }
將對象組合成樹形結構以表示「部分-總體」的層次結構。組合模式使得用戶對單個對象和組合對象的使用具備一致性。blog
引用大話設計模式的片斷:「當發現需求中是體現部分與總體層次結構時,以及你但願用戶能夠忽略組合對象與單個對象的不一樣,統一地使用組合結構中的全部對象時,就應該考慮組合模式了。」
經過上面的簡單講解,咱們知道了,組合模式意圖是經過總體與局部之間的關係,經過樹形結構的形式進行組織複雜對象,屏蔽對象內部的細節,對外展示統一的方式來操做對象,是咱們處理更復雜對象的一個手段和方式。如今再結合上面的代碼,想一想文章開頭提出的公司OA系統如何進行設計。