定义:
将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
组合模式也叫合成模式,有时又叫做部分-整体模式(Part-Whole),主要用来描述部分与整体的关系。
示例一:组合模式(通用版)
1. 类图21-6
2. 类图说明
Component:抽象构件角色。定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性。
Leaf:叶子构件。叶子对象,其下再也没有其他分支,也就是遍历的最小单位。
Composite:树枝构建。树枝对象,它的作用是组合树枝节点和叶子节点形成的一个树形结构。
3.代码清单
#include <QCoreApplication>
#include <QDebug>
// ********** 1.组合模式(通用版),代码清单21-1:***************//
//抽象构件
class Component
{
public:
virtual void doSomething(){qDebug() << "leaf";}
virtual void add(Component* component){}
virtual bool isLeaf() = 0;
};
//树枝构件
class Composite:public Component
{
public:
void add(Component* component)
{
this->m_component.push_back(component);
}
void remove(Component* component)
{
this->m_component.removeOne(component);
}
QList<Component*> getChildren()
{
return this->m_component;
}
virtual bool isLeaf()
{
return false;
}
virtual void doSomething()
{
if (!isLeaf())
{
QList<Component*> lists = getChildren();
QList<Component*>::ConstIterator iter = lists.begin();
while(iter != lists.end())
{
Component* component = *iter;
component->doSomething();
++iter;
}
}
qDebug() << "root";
}
private:
QList<Component*> m_component;
};
//树叶构件
class Leaf:public Component
{
public:
virtual bool isLeaf()
{
return true;
}
virtual void doSomething()
{
if (isLeaf())
{
Component::doSomething();
}
}
};
int main()
{
Composite *root = new Composite();
root->doSomething();
Component *branch = new Composite();
Component *leaf = new Leaf();
root->add(branch);
branch->add(leaf);
root->doSomething();
return 0;
}
三、组合模式的应用
1. 优点:
高层模块调用简单。 一颗树形机构中的所有节点都是Component, 局部和整体对调用者来说没有任何区别,也就是说,高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。
节点自由增加。使用了组合模式后,如果想增加一个树枝节点,树叶节点都很容易了,只要找到它的父节点就行,非常容易扩展,符合开闭原则,对以后的维护非常有利。
2. 缺点:
组合模式有一个非常明显的缺点,使用时的定义,直接使用了实现类,在面向接口编程上很不恰当,与依赖倒置原则冲突,使用时候要考虑清楚,它限制了接口的影响范围。
3. 使用场景:
维护和展示部分-整体关系的场景,如树形菜单、文件和文件夹管理。
从一个整体中能够独立出部分模块或功能的场景。
4. 注意事项:
只要是树形结构,就要考虑使用组合模式,只要是体现局部和整体的关系的时候,而且这种关系比较深,考虑一下组合模式。
四、最佳实践
组合模式在项目中到处都有,比如现在页面结构一般都是上下结构,上面放系统的logo,下面分为两部分:左边是导航菜单,右边是展示区,左边的导航菜单一般都是树形的结构,比较清晰,有非常多的javascript源码实现了类似的属性菜单。
大家常用的XML结构也是一个属性结构,根节点、元素节点、值元素这些都与我们的组合模式相匹配。
我们自己本身也是一个树状结构的树枝或树叶。根据我能够找到我的父母,根据父母可以找到爷爷奶奶,很典型的树形结构,且很规范。
参考文献《秦小波. 设计模式之禅》(第2版) (华章原创精品) 机械工业出版社