组合模式
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。
目的:当整体和部分的功能具有极大的相似性的时候,使用该模式将整个结构简单化,对于整体和部分都提供统一的接口,方便使用。
使用情形:
- 常用于树形结构的表示,表示部分-整体的层次结构
- 整体、部分存在高度重合,需要用户忽略些许不同,使用统一接口的时候
Component:组合对象的接口声明,实现部分和整体的共同对外接口。
Leaf:具体到部分的类,不可再分的叶子对象,因此改部分的删除和添加本类对象常不进行具体实现
Composite:容器对象,用来存储子部分,相当于枝干,存在对叶子对象进行添加和删除的操作接口
在实现的时候,有两种可用于选择:
- 叶子对象和容器对象分离,继承于接口
- 叶子对象和容器对象合并,但一类,设定成员vector等进行子部分存储。
根据上面的uml可以知道两种使用的差别。
- 分离:容易进行拓展、从实现上更有结构肝、对于各种类型的文件或者子部分可用实现自己的特殊需求
- 合并:逻辑简单、代码实现简单,但是不易进行拓展,对于各种子部分的特殊需求实现太过于复杂,所以常用于很明确不拓展的但类型情况处理
优点:
- 将复杂的对象分为清晰的层次结构,并且利于子部分的拓展
- 部分整体的统一接口,便于用户使用
- 对于复杂且接口相似的树结构进行简单化
缺点:
- 违反了依赖倒转
- 对于部分和整体的接口具有一定的限制性,需要双方接口存在高度的统一性
// CompositeModel.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class CMyFile
{
protected:
string m_name;
//string path;
public:
//查改
virtual string getName() = 0;
void setName(string str) { m_name = str; }
//增删
virtual void addFile(CMyFile* file) = 0;
virtual void removeFile(int index) = 0;
//显示
virtual void show() = 0;
};
class CTxtFile:public CMyFile
{
public:
string getName() { return (m_name + ".txt"); }
void addFile(CMyFile* file) {}
void removeFile(int index) {}
void show() { cout << "Text File :" + m_name + ".txt" << endl; }
};
class CVideoFile :public CMyFile
{
public:
string getName() { return (m_name + ".mp4"); }
void addFile(CMyFile* file) {}
void removeFile(int index) {}
void show() { cout << "Video File :" + m_name + ".mp4" << endl; }
};
class CFolder :public CMyFile
{
private:
vector<CMyFile*> m_file;
public:
string getName() { return m_name; }
void addFile(CMyFile* file) { m_file.push_back(file); }
void removeFile(int index) { m_file.erase(std::begin(m_file) + index); }
void show() {
cout << "Folder :" + m_name << endl;
for (int i = 0; i < m_file.size(); ++i)
{
if(NULL == m_file[i])
continue;
m_file[i]->show();
}
}
};
class CMyFile2
{
protected:
string m_name;
string m_suffix;
vector<CMyFile2*> m_file;
//string path;
public:
//查改
string getName() { return m_name; }
void setName(string str) { m_name = str; }
string getSuffix() { return m_suffix; }
void setSuffix(string suff) { m_suffix = suff; }
//增删
void addFile(CMyFile2* file) { m_file.push_back(file); }
void removeFile(int index) { m_file.erase(std::begin(m_file) + index); }
void show() {
cout << m_name + m_suffix << endl;
for (int i = 0; i < m_file.size(); ++i)
{
if (NULL == m_file[i])
continue;
m_file[i]->show();
}
}
};
int main()
{
//File 1
cout << "Test 1(more Class):" << endl;
CMyFile* testFile1 = new CFolder;
testFile1->setName("Folder 1");
CMyFile *text = new CTxtFile;
text->setName("Test1 Text File");
CMyFile *video = new CVideoFile;
video->setName("Test1 Video File");
testFile1->addFile(text);
testFile1->addFile(video);
testFile1->show();
cout << endl;
cout << endl;
//File 2
cout << "Test 1(one Class):" << endl;
CMyFile2* testFile2 = new CMyFile2;
testFile2->setName("Folder 2");
testFile2->setSuffix("");
CMyFile2* text2 = new CMyFile2;
text2->setName("Test2 Text File");
text2->setSuffix(".txt");
CMyFile2* video2 = new CMyFile2;
video2->setName("Test2 video File");
video2->setSuffix(".mp4");
testFile2->addFile(text2);
testFile2->addFile(video2);
testFile2->show();
}