Composite组合模式——对象结构模式
1.意图
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
Composite模式的关键是一个抽象类,它既可以代表图元,又可以代表图元的容器。
2.适用性
- 你想表示对象的部分-整体层次结构
- 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
3.结构
4.参与者
- Component
—— 为组合中的对象声明接口
—— 在适当的情况下,实现所有类共有接口的缺省行为
—— 声明一个接口用于访问和管理Component的子组件
—— (可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
- Leaf
—— 在组合中表示叶子节点对象,叶节点没有子节点
—— 在组合中定义图元对象的行为
- Composite
—— 定义有子部件的那些部件的行为
—— 存储子部件
—— 在Component接口中实现与子部件有关的操作
- Client
—— 通过Component接口操纵组合部件的对象
5.效果
优点:
1、节点增加和减少是非常自由和方便的,这也是树形结构的一大特点;
2、所有节点,不管是分支节点还是叶子结点,不管是调用一个结点,还是调用一个结点群,都是非常方便的。
缺点:
1、组合模式在定义树叶和树枝时直接使用了实现类,不符合面向对象接口编程。与依赖倒置原则冲突。
6.相关模式
通常部件-父部件连接用于Responsibility of Chain模式。
Decorator模式经常与Composite模式一起使用。当装饰和组合一起使用时,它们通常有一个公共的父类。因此装饰必须支持具有Add,Remove和GetChild操作的Component接口。
Flyweight让你共享组件,但不再能引用他们的父部件。
Itertor可用来遍历Composite。
Visitor将本来应该分布在Composite和Leaf类中的操作和行为局部化。
7.案例实现
公司部门架构,总部,部门、分部(分部又要自己的部门)。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class ComponentPtr
{
protected:
std::string m_strName;
public:
ComponentPtr(std::string str):m_strName(str){}
virtual void add(ComponentPtr* p) = 0;
virtual void remove(ComponentPtr* p) = 0;
virtual void display() = 0;
};
class LeafPtr : public ComponentPtr
{
public:
LeafPtr(string str) : ComponentPtr(str) {}
void add(ComponentPtr* p) { cout << "Leaf cannot add" << endl; }
void remove(ComponentPtr* p) { cout << "Leaf cannot remove" << endl; }
void display() { cout << m_strName << endl; }
};
class CompositePtr : public ComponentPtr
{
private:
// 这里使用智能指针不用自己释放new的内存
std::vector<std::shared_ptr<ComponentPtr>> m_vec;
public:
CompositePtr(std::string str) : ComponentPtr(str) {};
~CompositePtr() { if (!m_vec.empty()) { m_vec.clear(); } }
void add(ComponentPtr* p)
{
auto it = find_if(m_vec.begin(), m_vec.end(), [p](std::shared_ptr<ComponentPtr> ptr) {return p == ptr.get(); });
if (it == m_vec.end())
{
m_vec.push_back(std::shared_ptr<ComponentPtr>(p));
}
}
void remove(ComponentPtr * p)
{
auto it = find_if(m_vec.begin(), m_vec.end(), [p](std::shared_ptr<ComponentPtr> ptr) {return p == ptr.get(); });
if (it == m_vec.end()) { return; }
m_vec.erase(it);
}
void display()
{
for (auto it = m_vec.cbegin(); it != m_vec.cend(); it++)
{
(*it)->display();
}
}
};
int main()
{
CompositePtr* p = new CompositePtr("总部");
p->add(new LeafPtr("总部财务部门"));
p->add(new LeafPtr("总部人力资源部门"));
CompositePtr* p1 = new CompositePtr("上海分部");
p1->add(new LeafPtr("上海分部财务部门"));
p1->add(new LeafPtr("上海分部人力资源部门"));
p->add(p1);
p->display();
return 0;
}
设计模式系列 https://blog.youkuaiyun.com/nie2314550441/article/details/105849726