转载自:
http://patmusing.blog.163.com/blog/static/135834960201002321018760/
在面向对象的系统中,我们经常会遇到一类具有“容器”特征的对象,即它们在充当对象的同时,又是其他对象的容器。
举例:
在操作系统中,文件的概念很广泛,其中文件可以是普通文件,也可以是目录(在Unix中,设备也是文件),目录中可以存放文件。Composite设计模式就是将“客户代码与复杂的对象容器结构”解耦,让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象(文件)一样来处理复杂的对象容器(目录)。
“Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.” – GoF
调用Directory类对象的process函数,和调用PhysicalFile类对象的process一样简单。
从上面的UML类图中,可以看出Directory和File这两个类之间的关系:
1. Directory “is a”File
2. Directory “has a(more)” File
这是典型的递归结构。因此在处理递归问题时,如果必要,可以考虑采用Composite模式。后面要讲到的Decorator模式也是如此。
// Composite.h
#include <iostream>
#include <list>
using namespace std;
class File
{
public:
virtual void process() = 0;
// 虚函数:增加一个文件
virtual void add(File* file)
{
}
// 虚函数:删除一个文件
virtual void remove(File* file)
{
}
public:
virtual ~File()
{
cout << "in the destructor of File..." << endl;
}
};
// 叶子节点
class PhysicalFile : public File
{
public:
void process()
{
cout << "process() in PhysicalFile..." << endl;
}
public:
~PhysicalFile()
{
cout << "in the destructor of PhysicalFile..." << endl;
}
};
// 容器节点:Composite节点
class Directory : public File
{
private:
list<File*> file_list;
public:
Directory()
{
}
void process()
{
cout << "process() in Directory..." << endl;
if(!file_list.empty())
{
for(list<File*>::iterator it = file_list.begin(); it != file_list.end(); it++)
{
File* f = *it;
f->process();
}
}
}
void add(File* file)
{
file_list.push_back(file);
}
void remove(File* file)
{
file_list.remove(file);
}
public:
~Directory()
{
cout << "in the destructor of Directory..." << endl;
}
};
// Composite.cpp
#include "Composite.h"
int main(int argc, char **argv)
{
File *f1 = new Directory;
File *f2 = new Directory;
File *f3 = new PhysicalFile;
f2->add(f3);
f1->add(f2);
File *f4 = new Directory;
File *f5 = new Directory;
File *f6 = new Directory;
File *f7 = new PhysicalFile;
f6->add(f7);
f5->add(f6);
f4->add(f5);
f1->add(f4);
f1->process();
f1->remove(f4);
cout << "+++++++++++++++++++++++" << endl;
f1->process();
// STL container中的元素是指针对象,那么必须手动删除。
delete f1;
delete f2;
delete f3;
delete f4;
delete f5;
delete f6;
delete f7;
return 0;
}
上述程序中,各对象之间的关系如下图:
其中f3和f7为PhysicalFile对象。f1包含了f2和f4,f2包含了f3,f4包含了f5,f5包含了f6,f6包含了f7。
运行结果如下:
process() in Directory... // f1
process() in Directory... // f2
process() in PhysicalFile... // f3
process() in Directory... // f4
process() in Directory... // f5
process() in Directory... // f6
process() in PhysicalFile... // f7
+++++++++++++++++++++++ // 删除f4后的输出(可以看到f4及其包含的对象全部被删除了)
process() in Directory... // f1
process() in Directory... // f2
process() in PhysicalFile... // f3
in the destructor of Directory...
in the destructor of File...
in the destructor of Directory...
in the destructor of File...
in the destructor of PhysicalFile...
in the destructor of File...
in the destructor of Directory...
in the destructor of File...
in the destructor of Directory...
in the destructor of File...
in the destructor of Directory...
in the destructor of File...
in the destructor of PhysicalFile...
in the destructor of File...