组合模式,将对象组合成树形构造以示意“局部-整体”的层次结构,组合模式使得用户对单个对象和组合对象的应用具备一致性。ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ ——Erich Gamma et. al.

伊始

组合(Composite)模式,又叫作局部-整体模式,它是一种将对象组合成树状的层次结构的模式,用来示意“局部-整体”的关系,使用户对单个对象和组合对象具备统一的拜访性。

构造模型

■ 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办法的,这里在抽象类提供了一份默认实现。

  • 叶子对象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_;};
  • 用户应用

这里假如用户须要设计一个治理商品类别树的场景,如下

- 商品  - 服装    - 男装    - 女装  - 书籍    - 中文书籍    - 外文书籍

应用组合模式,如下

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. 不容易用继承的办法来减少构件的新性能;

End

学习是输出,分享是输入,保持继续分享。。。