组合模式,将对象组合成树形结构以表示“部分-总体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具备一致性。ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ ——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
因为叶子对象没有add
和remove
方法的,这里在抽象类提供了一份默认实现。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
学习是输入,分享是输出,坚持持续分享。。。继承