组合模式

scorlw 发布于

组合模式

设计模式

Composite模式也叫组合模式,是构造型的设计模式之一。通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树。

image-20201012225220821

Component(树形结构的节点抽象)

  • 为所有的对象定义统一的接口(公共属性,行为等的定义)

  • 提供理子节点对象的接口方法

  • 【可选】提供管理父节点对象的接口方法

    Leaf(树形结构的叶节点)

Component的实现子类

Composite(材形结构的枝节点)

Component的实现子类

适用于:

单个对象和组合对象的使用具有一致性,将对象组合成树形结构以表示“部分–整体”

代码

想要构建一个目录的树状结构,包括文件/文件夹的增删与读取。

1
2
3
4
5
C
111dir
222dir
bbb.txt
aaa.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <iostream>
#include <string>
#include <list>

using namespace std;

//抽象文件类,包括文件和文件夹
class IFile
{
public:
virtual void display() = 0;//显示文件名
virtual int add(IFile* ifile) = 0;//增加文件
virtual int remove(IFile* ifile) = 0;//移除文件
virtual list<IFile *>* getChild() = 0;//获得该目录下的子文件
protected:
private:
};

//文件
class File : public IFile
{
public:
File(string name)
{
m_name = name;
}
virtual void display()
{
cout << m_name << endl;
}
//文件类不支持增加文件
virtual int add(IFile* ifile)
{
return -1;
}
//文件类不支持移除文件
virtual int remove(IFile* ifile)
{
return -1;
}
//文件类没有子文件
virtual list<IFile *>* getChild()
{
return NULL;
}
protected:
private:
string m_name;
};

//文件夹
class Dir : public IFile
{
public:
//文件夹包括名字和其子目录
Dir(string name)
{
m_name = name;
m_list = new list<IFile *>;
m_list->clear();
}
virtual void display()
{
cout << m_name << endl;
}
virtual int add(IFile* ifile)
{
m_list->push_back(ifile);
return 0;
}
virtual int remove(IFile* ifile)
{
m_list->remove(ifile);
return 0;
}
virtual list<IFile *>* getChild()
{
return m_list;
}
protected:
private:
string m_name;
list<IFile *>* m_list;
};

//递归的显示树
void showTree(IFile* root, int level)
{
if(root == NULL)
return;
for(int i = 0; i < level; i++)
{
cout << "\t";
}
//1.显示根节点
root->display();

//2.若根节点有孩子
//1)孩子是文件,显示名字
//2)孩子是目录,显示子目录
list<IFile*> *mylist = root->getChild();
if(mylist != NULL)//说明是目录
{
for(auto it = mylist->begin(); it != mylist->end(); it++)
{
if((*it)->getChild() == NULL)
{
for(int i = 0; i <= level; i++)
{
cout << "\t";
}
(*it)->display();
}
else
{
showTree(*it, level + 1);
}
}
}

}

int main()
{
Dir* root = new Dir("C");
root->display();

Dir* dir1 = new Dir("111dir");
File* aaafile = new File("aaa.txt");

root->add(dir1);
root->add(aaafile);

list<IFile *>* list = root->getChild();
for(auto it = list->begin(); it != list->end(); it++)
{
(*it)->display();
}

Dir* dir2 = new Dir("222dir");
File* bbbfile = new File("bbb.txt");

dir1->add(dir2);
dir1->add(bbbfile);

for(auto it = list->begin(); it != list->end(); it++)
{
(*it)->display();
}

cout << "showTree" << endl;
showTree(root,0);
cout << "Hello world!" << endl;
return 0;
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
C
111dir
aaa.txt
111dir
aaa.txt
showTree
C
111dir
222dir
bbb.txt
aaa.txt
Hello world!