设计模式之组合模式
来源:互联网 发布:电脑软件转移工具 编辑:程序博客网 时间:2024/06/05 00:39
1、组合模式(Composite):将对象组合成树形结构已表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
UML图如下:
参与者:
Component
----为组合中的对象声明接口
----在适当的情况下,实现所有类共有接口的缺省行为。
----在声明一个接口用于访问和管理Component的子组件
Leaf
----在组合中表示节点对象,叶节点没有子节点
----在组合中定义图元对象的行为
Composite
----定义有子部件的哪些部件的行为
----存储子部件
Client
----通过Component 接口操纵组合部件的队形。
协作:
用户使用Component类接口与组合结构中的对象进行交互。如果接收者是一个叶节点,则直接处理请求。如果接收者是Composite,它通常将请求发送给他们的子部件,在转发请求之前与之后可能执行一些辅助操作。
2、组合模式的透明方式与安全方式
1)透明方法:
也就是说在Component中声明所有用来管理子对象的方法,其中包括Add,Remove等。这样实现Component接口所有的子类都具备了Add和Remove。
这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口,但问题也很明显。因为Leaf类本身不具备Add(),Remove方法的功能,所以实现它是没有意义的。
2)安全方法:
也就是在Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样的做就不会出现刚才提出的问题,由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。
3、如何使用组合模式?
答:当你发现需求中是体系部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的的不同,统一使用组合结构中的所有对象时,就应该考虑用组合模式了。
4、组合模式的好处?
答:组合模式定义了包含基本对象,组合对象的类层次结构,基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象。用户不用关心到底是处理一个叶节点还是处理一个组合组件。也就用不着为定义组合而写一些选择判断语句了。组合模式让客户可以一致地使用组合结构和单个对象。
代码实现如下;
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
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
/* Component为组合中的对象声明接口,在适当情况下,
实现所有类共有接口的默认行为。声明一个接口用于
访问和管理Component的子部件 */
class Component
{
protected:
string name;
public:
Component(string);
/* 通常都用Add和Remove的方法
来提供增加和移除树叶或树枝的功能*/
virtual void Add(Component *) = 0;
virtual void Remove(Component *) = 0;
virtual void Display(int) = 0;
};
Component::Component(string name)
{
Component::name = name;
}
/* Leaf在组合中表示叶节点对象,叶节点没有子节点。 */
class Leaf : public Component
{
public:
Leaf(string name): Component(name) {}
void Add(Component *);
void Remove(Component *);
void Display(int);
};
/* 由于叶子没有增加分枝和树叶,所以Add和Remove方法实现它没有意义,
但这样做可以消除叶节点和枝节点对象在抽象层次的区别,它们具有
完全一致的接口。 */
void Leaf::Add(Component *p_c)
{
cout << "Cannot add to a leaf" << endl;
}
void Leaf::Remove(Component *p_c)
{
cout << "Cannot remove from a leaf" << endl;
}
/* 叶子节点的具体方法,此处是显示器名称和级别 */
void Leaf::Display(int depth)
{
for (int i = 0; i < depth; ++i)
{
cout << "-";
}
cout << name << endl;
}
/* Component定义有枝节点行为,用来存储子部件
在Component接口中实现与子部件有关的操作,
比如增加Add和删除Remove。 */
class Composite : public Component
{
private:
vector<Component *> v;
public:
Composite(string name) : Component(name) {}
void Add(Component *);
void Remove(Component *);
void Display(int);
};
void Composite::Add(Component *p_c)
{
v.push_back(p_c);
}
void Composite::Remove(Component *p_c)
{
vector<Component *>::iterator it;
it = find(v.begin(), v.end(), p_c);
v.erase(it);
}
/* 显示节点名称并对其下级进行遍历 */
void Composite::Display(int depth)
{
for (int i = 0; i < depth; ++i)
{
cout << "-";
}
cout << name << endl;
int cnt = v.size();
for (int i = 0; i < cnt; ++i)
{
v[i]->Display(depth + 2);
}
}
int main()
{
Composite *root = new Composite("root");
Leaf *leafA = new Leaf("Leaf A");
root->Add(leafA);
root->Add(new Leaf("Leaf B"));
Composite *comp = new Composite("Composite X");
comp->Add(new Leaf("Leaf XA"));
comp->Add(new Leaf("Leaf XB"));
root->Add(comp);
root->Display(1);
root->Remove(leafA);
root->Display(1);
return 0;
}
DP书上给出的定义:将对象组合成树形结构以表示“部分-整体”的层次结构。组合使得用户对单个对象和组合对象的使用具有一致性。注意两个字“树形”。这种树形结构在现实生活中随处可见,比如一个集团公司,它有一个母公司,下设很多家子公司。不管是母公司还是子公司,都有各自直属的财务部、人力资源部、销售部等。对于母公司来说,不论是子公司,还是直属的财务部、人力资源部,都是它的部门。整个公司的部门拓扑图就是一个树形结构。
下面给出组合模式的UML图。从图中可以看到,FinanceDepartment、HRDepartment两个类作为叶结点,因此没有定义添加函数。而ConcreteCompany类可以作为中间结点,所以可以有添加函数。那么怎么添加呢?这个类中定义了一个链表,用来放添加的元素。
相应的代码实现为:
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
{
public:
Company(string name)
{
m_name = name;
}
virtual ~Company() {}
virtual void Add(Company *pCom) {}
virtual void Show(int depth) {}
protected:
string m_name;
};
//具体公司
class ConcreteCompany : public Company
{
public:
ConcreteCompany(string name): Company(name) {}
virtual ~ConcreteCompany() {}
void Add(Company *pCom)
{
m_listCompany.push_back(pCom); //位于树的中间,可以增加子树
}
void Show(int depth)
{
for(int i = 0; i < depth; i++)
cout << "-";
cout << m_name << endl;
list<Company *>::iterator iter = m_listCompany.begin();
for(; iter != m_listCompany.end(); iter++) //显示下层结点
(*iter)->Show(depth + 2);
}
private:
list<Company *> m_listCompany;
};
//具体的部门,财务部
class FinanceDepartment : public Company
{
public:
FinanceDepartment(string name): Company(name) {}
virtual ~FinanceDepartment() {}
virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点
{
for(int i = 0; i < depth; i++)
cout << "-";
cout << m_name << endl;
}
};
//具体的部门,人力资源部
class HRDepartment : public Company
{
public:
HRDepartment(string name): Company(name) {}
virtual ~HRDepartment() {}
virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点
{
for(int i = 0; i < depth; i++)
cout << "-";
cout << m_name << endl;
}
};
int main()
{
Company *root = new ConcreteCompany("总公司");
Company *leaf1 = new FinanceDepartment("财务部");
Company *leaf2 = new HRDepartment("人力资源部");
root->Add(leaf1);
root->Add(leaf2);
//分公司A
Company *mid1 = new ConcreteCompany("分公司A");
Company *leaf3 = new FinanceDepartment("财务部");
Company *leaf4 = new HRDepartment("人力资源部");
mid1->Add(leaf3);
mid1->Add(leaf4);
root->Add(mid1);
//分公司B
Company *mid2 = new ConcreteCompany("分公司B");
FinanceDepartment *leaf5 = new FinanceDepartment("财务部");
HRDepartment *leaf6 = new HRDepartment("人力资源部");
mid2->Add(leaf5);
mid2->Add(leaf6);
root->Add(mid2);
root->Show(0);
delete leaf1;
delete leaf2;
delete leaf3;
delete leaf4;
delete leaf5;
delete leaf6;
delete mid1;
delete mid2;
delete root;
return 0;
}
- 设计模式之组合模式
- 设计模式之组合模式
- 设计模式之组合模式
- 设计模式之--组合模式
- 设计模式之组合模式
- 设计模式之组合模式
- 设计模式之组合模式
- 设计模式之组合模式
- 设计模式之---组合模式
- 设计模式之组合模式
- 设计模式之组合模式
- 设计模式之-------------组合模式
- 设计模式之组合模式
- 设计模式之组合模式
- 设计模式之组合模式
- 设计模式 之 组合模式
- 设计模式之组合模式
- 设计模式之组合模式
- 强制踏进那些我们大脑中没有知识“涉足”的“净土”
- uniGUI 0.93在Delphi XE4下的安装问题
- java动态代理(JDK和cglib)
- hdoj 2564 词组缩写 水题,水过~
- 详解之建造者模式
- 设计模式之组合模式
- C++设计模式之简单工厂模式(二)
- 二分查找之美:二分查找及其变体的正确性以及构造方式
- UVA - 10913Walking on a Grid(记忆化搜索)
- 【九度OJ】1038【贪心】
- poj1023
- 网上看到的一张图,销售-客户各层次关系表
- LeetCode | Gray Code(格雷码)
- 【阅读】《如何高效学习》——第一部分1