組合(Composite)模式 in C++

組合模式,將對象組合成樹形結構以表示「部分-總體」的層次結構,組合模式使得用戶對單個對象和組合對象的使用具備一致性。ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ ——Erich Gamma et. al.

伊始

組合(Composite)模式,又叫做部分-總體模式,它是一種將對象組合成樹狀的層次結構的模式,用來表示「部分-總體」的關係,使用戶對單個對象和組合對象具備一致的訪問性。ide

結構模型

組合模式結構示意圖

■ Component:抽象的組件對象,爲組合中的對象聲明接口,讓客戶端能夠經過這個接口來訪問和管理整個對象結構,能夠在裏面爲定義的功能提供缺省的實現。
■ Leaf:葉子節點對象,定義和實現葉子對象的行爲,再也不包含其餘的子節點對象。
■ Composite:組合對象,一般會存儲子組件,定義包含子組件的那些組件的行爲,並實如今組件接口中定義的與子組件有關的操做。
■ Client:客戶端,經過組件接口來操做組合結構裏面的組件對象。函數

實現域

  • Component定義
struct Component {
  virtual ~Component(){}

  ABSTRACT(void process());

  virtual void add(Component*) {
    return;
  }

  virtual void remove(Component*) {
    return;
  }
};

注意,上面ABSTRACT是一個C++封裝宏,表示定義的方法是純虛函數,亦即接口,原型以下:學習

#define ABSTRACT(...) virtual __VA_ARGS__ = 0

因爲葉子對象沒有addremove方法的,這裏在抽象類提供了一份默認實現。spa

  • 葉子對象Leaf定義
struct Leaf : Component {
  OVERRIDE(void process()) {
    /* do process self */
  }
};

其中,上面OVERRIDE也是一個C++封裝宏,表示實現或者覆寫父類的接口(或方法),原型以下:設計

#define OVERRIDE(...) virtual __VA_ARGS__ override
  • 組合對象Composite定義
using Components = std::list<Component*>;
struct Composite : Component {
  explicit  Composite(const std::string& name) : name_{name} {}

  OVERRIDE(void process()) {
    /* do process self */

    /* process child */
    for (auto& c : components_) {
        c->process();
    }
  }

  OVERRIDE(void add(Component* component)) {
    components_.push_back(component)
  }

  OVERRIDE(void remove(Component* component)) {
    components_.remove(component)
  }

private:
  std::string name_;
  Components components_;
};
  • 用戶使用

這裏假設用戶須要設計一個管理商品類別樹的場景,以下code

- 商品
  - 服裝
    - 男裝
    - 女裝
  - 書籍
    - 中文書籍
    - 外文書籍

使用組合模式,以下component

void process(Component& component) {
  component.process();
}

int main() {
  Composite root("商品");
  Composite dress("服裝");
  Composite book("書籍");

  Leaf man_dress("男裝");
  Leaf women_dress("女裝");
  Leaf book_zh("中文書籍");
  Leaf book_foreign("外文書籍");

  root.add(&dress);
  dress.add(&man_dress);
  dress.add(&women_dress);

  root.add(&book);
  book.add(&book_zh);
  book.add(&book_foreign);
  
  process(root);
}

優缺點

  • 優勢

1. 定義了包含基本對象和組合對象的類層次結構,基本對象能夠被組合成複雜的組合對象,而組合對象又能夠組合成更復雜的組合對象,能夠不斷地遞歸組合下去,從而構成一個統一的組合對象的類層次結構。
2. 組合模式使得客戶端代碼能夠一致地處理單個對象和組合對象,無須關心本身處理的是單個對象,仍是組合對象,這簡化了客戶端代碼;
3. 更容易在組合體內加入新的對象,客戶端不會由於加入了新的對象而更改源代碼,知足「開閉原則」;對象

  • 缺點

1. 不容易限制容器中的構件;
2. 不容易用繼承的方法來增長構件的新功能;blog

End

學習是輸入,分享是輸出,堅持持續分享。。。繼承

相關文章
相關標籤/搜索