1、定义:组合多个对象形成树形结构以表示具有部分-整体关系的层次结构
2、组合模式让客户端统一对待单个对象和组合对象
3、组合模式又称为部分-整体模式
4、将对象组织到树形结构中,可以用来描述整体与部分的关系
组合模式包含以下3个角色:
1、Component(抽象构件):是组合模式中最重要的接口或抽象类,它声明了访问及管理子组件的方法,如增加、删除、获取子组件等
2、Leaf(叶子构件):是组合模式中的基本对象,它实现了抽象组件中定义的行为,并且没有子组件
3、Composite(容器对象):这是包含子组件的组合对象,它可以包含叶子组件和其它容器组件,形成一个树形结构。
//定义接口(Component)
class Component
{
public:
virtual ~Component() = default;
virtual void add(std::shared_ptr component) = 0;
virtual void remove(Component* component) = 0;
virtual Component* getChild(int index) = 0;
virtual int getChildIndex() const = 0;
virtual bool isComposite() const = 0;
virtual bool isLeaf() const = 0;
virtual void operatoin() const = 0;
};
创建一个或多个叶子组件类,继承实现抽象组件接口。在叶子组件类中,实现了抽象组件接口中定义的方法,但叶子组件不会再有子组件,所以添加和删除子组件方法执行空操作
//实现叶子组件(Leaf)类
class Leaf : public Component
{
public:
Leaf(const string &name) : m_name(name){}
void add(std::shared_ptr component) override
{
cout << "Leaf unable add children" << endl;
}
void remove(Component* component) override
{
cout << "Leaf unable remove children" << endl;
}
Component* getChild(int index) override
{
return nullptr;
}
int getChildIndex() const override
{
return 0;
}
bool isComposite() const override
{
return false;
}
bool isLeaf() const override
{
return true;
}
void operatoin() const override
{
cout << "Leaf operation" << endl;
}
private:
string m_name;
};
创建一个容器组件类,继承实现抽象组件接口。在容器组件类中,除了实现抽象组件接口中定义的方法外,还需要维护一个子组件列表,提供方法来添加、删除和获取子组件。
//实现容器组件类(Composite)类
class Composite : public Component
{
public:
Composite(const string &name) : m_name(name) {}
void add(std::shared_ptr component) override
{
m_children.push_back(std::move(component));
}
void remove(Component* component) override
{
auto it = std::find_if(m_children.begin(), m_children.end(), [component](const std::shared_ptr& t) {
return t.get() == component;
});
if (it != m_children.end())
m_children.erase(it);
else
cout << "Composite not found children" << endl;
}
Component* getChild(int index) override
{
if (index < 0 || index >= m_children.size())
return nullptr;
return m_children[index].get();
}
int getChildNum() const override
{
return m_children.size();
}
bool isComposite() const override
{
return true;
}
bool isLeaf() const override
{
return false;
}
void operatoin() const override
{
cout << "Composite operation" << endl;
for (int i = 0; i < m_children.size(); ++i)
m_children.at(i)->operatoin();
}
private:
string m_name;
vector> m_children;
};
在客户端,可以创建叶子组件和容器组件实例,并将它们组合成树形结构
int main()
{
std::shared_ptr leafA = std::make_shared("leafA");
std::shared_ptr leafB = std::make_shared("leafB");
std::shared_ptr composite = std::make_shared("composite");
composite->add(std::move(leafA));
composite->add(std::move(leafB));
composite->operatoin();
}
这个示例中展示了组合模式的基本结构和使用方式,可以根据需要进行扩展,添加更多的组件类型、方法或操作
1、图形绘制:在图形系统中,图形对象可以是单独的形状(如圆形、矩形)或由多个形状组合成的复杂图形。使用组合模式可以统一处理单个形状和由形状组成的图形组合。
2、文件系统:文件系统中的文件和文件夹可以形成树形结构。文件夹可以包含其他文件夹或文件,使用组合模式可以一致地处理文件和文件夹的操作。
3、用户界面(GUI):用户界面组件(如按钮、面板、菜单)可以组成复杂的界面层次结构。组合模式可以帮助统一处理这些组件的操作和显示。
4、树形数据结构:在处理树形数据结构时,例如XML文档、目录结构或组织图,组合模式可以帮助简化对这些结构的操作。
5、组织架构:在公司或其他组织中,员工可以有不同的层级和角色。员工(单个节点)和部门(包含多个员工和部门的组合)可以使用组合模式来表示和处理。
#include
#include
#include
// 组件接口
class Component {
public:
virtual ~Component() = default;
virtual void render() const = 0;
};
// 叶子节点
class Button : public Component {
public:
Button(const std::string& name) : name(name) {}
void render() const override {
std::cout << "Rendering button: " << name << std::endl;
}
private:
std::string name;
};
// 组合节点
class Panel : public Component {
public:
~Panel() override = default;
void add(std::shared_ptr component) {
children.push_back(component);
}
void remove(std::shared_ptr component) {
auto it = std::remove(children.begin(), children.end(), component);
children.erase(it, children.end());
}
void render() const override {
std::cout << "Rendering panel" << std::endl;
for (const auto& child : children) {
child->render();
}
}
private:
std::vector> children;
};
// 客户端代码
int main()
{
// 创建按钮和面板
auto button1 = std::make_shared
1、可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,方便对整个层次结构进行控制
2、增加新的容器构件和叶子构件都很方便,符合开闭原则
3、为树形结构的面向对象实现提供了一种灵活的解决方案
1、在增加新构件时,很难对容器中的构件类型进行限制