1.组合模式的定义以及类图
组合模式通俗点来讲,就是数据结构中的树结构。其适用于单个对象和组合对象的使用具有一致性时(最典型的就是目录结构),将对象组合合成树形结构,以表示“部分-整体”。
具体的构造,根据其类图可以很容易看出来,其类图如下:
根据类图可知,组合模式主体为一个抽象基类,其派生类为叶节点对象和枝节点对象,其中叶节点就是标准的末端节点,其没有对应的子节点,所以只继承相关的功能函数Operarion。而枝节点是可以作为原抽象基类的整体的,所以其派生了所有的虚函数,使其可以增加或删除(add、remove)节点,并读取其下层的子节点(getChild),当然,其仍然会继承相关的功能函数Operation。这就是组合模式中的两种实例化对象的具体区别,通过根节点不断向下延伸,而末端节点必均为叶节点,而其中的分支节点都为枝节点。
2.组合模式的代码实现
这里采用了文件夹形式的构造,其抽象基类为AbFile,叶节点为File,枝节点为Folder。实例化的对象中包含了两种图片(jpg)和两种文本文件(txt),各自代表篮球中的詹姆斯和足球中的梅西。其中还增加一个输入根节点显示其属下所有节点的函数ShowAllFile,这是模仿树结构的形式实现的。
具体代码如下:
#include <iostream>
#include <string>
#include <list>
using namespace std;
class AbFile
{
public:
virtual void display() = 0;
virtual int add(AbFile* abfile) = 0;
virtual int remove(AbFile* abfile) = 0;
virtual list<AbFile*>* getChild() = 0;
};
class File : public AbFile
{
public:
File(string name, string type) : m_name(name), m_type(type) {}
void display() override
{
cout << "File is " << m_name << m_type << endl;
}
int add(AbFile* abfile) override { return -1; }
int remove(AbFile* abfile) override { return -1; }
list<AbFile*>* getChild() override { return NULL; }
private:
string m_name;
string m_type;
};
class Folder : public AbFile
{
public:
Folder(string name)
{
m_name = name;
m_child = new list<AbFile*>;
m_child->clear();
}
void display()
{
cout << "Folder name is " << m_name << endl;
}
int add(AbFile* abfile)
{
m_child->push_back(abfile);
return 1;
}
int remove(AbFile* abfile)
{
m_child->remove(abfile);
return 1;
}
list<AbFile*>* getChild()
{
return m_child;
}
private:
string m_name;
list<AbFile*>* m_child;
};
void ShowAllFile(AbFile* abfile)
{
if (abfile == NULL)
{
return;
}
list<AbFile*>* templist = abfile->getChild();
if (templist != NULL)
{
cout << " ";
abfile->display();
for (auto &s : *templist)
{
ShowAllFile(s);
}
}
else
{
abfile->display();
}
}
int main()
{
File* image1 = new File("foteball", ".jpg");
File* image2 = new File("basketball", ".jpg");
File* text1 = new File("Messi", ".txt");
File* text2 = new File("James", ".txt");
Folder* Person = new Folder("Person");
Folder* Person1 = new Folder("Person1");
Folder* Person2 = new Folder("Person2");
Person->add(Person1);
Person->add(Person2);
Person1->add(image1);
Person1->add(text1);
Person2->add(image2);
Person2->add(text2);
cout << "*****Person's Place*****" << endl;
ShowAllFile(Person);
cout << "*****Person1's Place*****" << endl;
ShowAllFile(Person1);
cout << "*****Person2's Place*****" << endl;
ShowAllFile(Person2);
}