1、介绍
组合模式(Composite)是一种结构型设计模式,也被称为部分-整体模式。它将复杂对象视为由多个简单对象(称为“组件”)组成的树形结构,这些组件能够共享相同的行为。每个组件都可能包含一个或多个子组件,而不需要了解子组件的具体类型。
在组合模式中,有三个关键角色:
(1)组件(Composite):这个抽象类或接口定义了所有组件都具有的公共行为。它通常有一个或多个方法来访问其子组件,并且可以包含一个指向子组件的指针数组。
(2)具体组件(Leaf):这是没有子组件的组件,它们直接实现了组件接口。这些是组合模式的叶子节点,不包含其他元素。
(3)复合组件(Composite):这是有子组件的组件,它们除了实现组件接口外,还负责维护子组件的列表,以及调用相应的方法对它们进行操作。
组合模式的优点:
(1)支持动态扩展和灵活的层次结构。
(2)降低组件间的耦合度,使得代码更易于理解和维护。
(3)可以统一处理所有类型的组件,无论是简单的还是复杂的。
2、示例
#include <iostream>
#include <string>
#include <vector>
// 抽象的组件类Element 描写全部部件共同拥有的行为
class Element
{
public:
Element(const std::string& name): m_name(name){}
virtual ~Element(){}
virtual void eat() = 0;
virtual void add(Element *) = 0;
virtual void remove(Element *) = 0;
virtual const std::string& getName()
{
return m_name;
}
protected:
std::string m_name;
};
// 具体组件类,叶子构件 Apple类
class Apple : public Element
{
public:
Apple(const std::string& name): Element(name){}
virtual ~Apple()
{
std::cout << "~Apple()" << std::endl;
}
void eat()
{
std::cout << "eat fruit type is apple" << std::endl;
}
void add(Element *pcomt){}
void remove(Element *pcomt){}
};
// 具体组件类,叶子构件 Banana类
class Banana : public Element
{
public:
Banana(const std::string& name): Element(name){}
virtual ~Banana()
{
std::cout << "~Banana()" << std::endl;
}
void eat()
{
std::cout << "eat fruit type is banana " << std::endl;
}
void add(Element *pcomt){}
void remove(Element *pcomt){}
};
// 具体组件类,叶子构件 Pear类
class Pear : public Element
{
public:
Pear(const std::string& name): Element(name){}
virtual ~Pear()
{
std::cout << "~Pear()" << std::endl;
}
void eat()
{
std::cout << "eat fruit type is pear" << std::endl;
}
void add(Element *pcomt){}
void remove(Element *pcomt){}
};
// 复合组件类 容器构件类 PlateComposite水果盘
class PlateComposite : public Element
{
public:
PlateComposite(const std::string& name): Element(name){}
virtual ~PlateComposite()
{
std::cout << "~PlateComposite()" << std::endl;
std::vector<Element *>::iterator it = _vecComp.begin();
while (it != _vecComp.end())
{
if (*it != NULL)
{
std::cout << "----delete " << (*it)->getName() << "----" << std::endl;
delete *it;
*it = NULL;
}
_vecComp.erase(it);
it = _vecComp.begin();
}
}
void eat()
{
for(auto iter : _vecComp){
iter ->eat();
}
}
void add(Element *pcomt)
{
_vecComp.push_back(pcomt);
}
void remove(Element *pcomt)
{
for (std::vector<Element *>::iterator it = _vecComp.begin(); it != _vecComp.end(); ++it)
{
if ((*it)->getName() == pcomt->getName())
{
if (*it != NULL)
{
delete *it;
*it = NULL;
}
_vecComp.erase(it);
break;
}
}
}
private:
std::vector<Element *> _vecComp;
};
int main()
{
Element *obj1 = new Apple("apple");
Element *obj2 = new Banana("banana");
Element *plate1 = new PlateComposite("zuhe_1");
plate1->add(obj1);
plate1->add(obj2);
plate1->eat();
std::cout << "-----------------------------------------------" << std::endl;
Element *obj3 = new Pear("pear");
Element *plate2 = new PlateComposite("zuhe_2");
plate2->add(obj3);
plate2->eat();
std::cout << "-----------------------------------------------" << std::endl;
plate1->add(plate2); // 将组合zuhe_2添加到组合zuhe_1中
plate1->eat();
std::cout << "-----------------------------------------------" << std::endl;
plate1->remove(obj1);
plate1->eat();
std::cout << "-----------------------------------------------" << std::endl;
// delete obj1;
// delete obj2;
if(nullptr != plate1){
delete plate1;
plate1 = nullptr;
}
return 0;
}
结果:
eat fruit type is apple
eat fruit type is banana
-----------------------------------------------
eat fruit type is pear
-----------------------------------------------
eat fruit type is apple
eat fruit type is banana
eat fruit type is pear
-----------------------------------------------
~Apple()
eat fruit type is banana
eat fruit type is pear
-----------------------------------------------
~PlateComposite()
----delete banana----
~Banana()
----delete zuhe_2----
~PlateComposite()
----delete pear----
~Pear()