组合模式 结构型设计模式
优点:
- 它可以让客户端以统一的方式处理单个对象和组合对象。
- 它可以让你更容易地增加新类型的组件。
缺点:
它可能使你的设计变得过于通用。有时候,只有叶子组件需要定义某些操作,但是由于通用性,你不得不在所有组件中定义这些操作。
满足的设计原理:
- 单一职责原则:每个类都只负责一项职责。在组合模式中,叶子组件只负责执行单一操作,而复合组件则负责组织和管理其子组件。
- 开闭原则:软件实体应该对扩展开放,对修改关闭。在组合模式中,你可以通过增加新的组件类型来扩展系统,而无需修改现有的代码。
- 里氏替换原则:子类应该能够替换其父类。在组合模式中,客户端可以使用统一的接口来处理单个对象和组合对象,而不需要关心它们的具体类型
常用实例:
- 图形用户界面:许多图形用户界面都使用了组合模式来组织和管理窗口、面板、按钮和文本框等组件。例如,在一个窗口中,你可以有一个面板,面板中又可以包含按钮和文本框等组件。
- 文件系统:文件系统通常使用组合模式来表示文件和文件夹的层次结构。文件夹可以包含文件和其他文件夹,而文件则是叶子节点。
- XML/HTML文档:XML和HTML文档也可以使用组合模式来表示其树形结构。文档中的每个元素都可以包含其他元素或文本内容。
类图:
代码:
#include "iostream"
#include "string"
#include <vector>
using namespace std;
class Component
{
public:
virtual ~Component(){};
virtual void Operation()=0;
//如果为了透明接口可以写成虚函数
//virtual void Add(Component* component) {};
//virtual void Remove(Component* componet) {};
};
class Leaf :public Component {
public:
void Operation()
{
cout<<"Leaf operation"<<endl;
}
};
class Composite :public Component {
public:
void Add(Component* component)
{
children_.push_back(component);
}
void Remove(Component* componet)
{
children_.erase(remove(children_.begin(),children_.end(),componet),children_.end());
}
void Operation()
{
cout<<"Composite operation"<<endl;
for (vector<Component*>::iterator it=children_.begin();it!=children_.end();it++)
{
(*it)->Operation();
}
}
private:
vector<Component*> children_;
};
int main ()
{
Leaf leaf1,leaf2;
Composite composite1,composite2;
composite1.Add(&leaf1);
composite1.Add(&composite2);
composite2.Add(&leaf2);
composite1.Operation();
return 0;
}