组合模式将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。
模式图:
适用场景:
- 你想表示对象的部分-整体层次结构。
- 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
举例:
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
|
namespace FactoryMethod_DesignPattern
{
using System;
using System.Collections;
abstract class Component
{
protected string strName;
public Component(string name)
{
strName = name;
}
abstract public void Add(Component c);
public abstract void DumpContents();
// other operations for delete, get, etc.
}
class Composite : Component
{
private ArrayList ComponentList = new ArrayList();
public Composite(string s) : base(s) {}
override public void Add(Component c)
{
ComponentList.Add(c);
}
public override void DumpContents()
{
// First dump the name of this composite node
Console.WriteLine( "Node: {0}" , strName);
// Then loop through children, and get then to dump their contents
foreach (Component c in ComponentList)
{
c.DumpContents();
}
}
}
class Leaf : Component
{
public Leaf(string s) : base(s) {}
override public void Add(Component c)
{
Console.WriteLine( "Cannot add to a leaf" );
}
public override void DumpContents()
{
Console.WriteLine( "Node: {0}" , strName);
}
}
/// <summary>
/// Summary description for Client.
/// </summary>
public class Client
{
Component SetupTree()
{
// here we have to create a tree structure,
// consisting of composites and leafs.
Composite root = new Composite( "root-composite" );
Composite parentcomposite;
Composite composite;
Leaf leaf;
parentcomposite = root;
composite = new Composite( "first level - first sibling - composite" );
parentcomposite.Add(composite);
leaf = new Leaf( "first level - second sibling - leaf" );
parentcomposite.Add(leaf);
parentcomposite = composite;
composite = new Composite( "second level - first sibling - composite" );
parentcomposite.Add(composite);
composite = new Composite( "second level - second sibling - composite" );
parentcomposite.Add(composite);
// we will leaf the second level - first sibling empty, and start
// populating the second level - second sibling
parentcomposite = composite;
leaf = new Leaf( "third level - first sibling - leaf" );
parentcomposite.Add(leaf);
leaf = new Leaf( "third level - second sibling - leaf" );
parentcomposite.Add(leaf);
composite = new Composite( "third level - third sibling - composite" );
parentcomposite.Add(composite);
return root;
}
public static int Main(string[] args)
{
Component component;
Client c = new Client();
component = c.SetupTree();
component.DumpContents();
return 0;
}
}
}
|
可以看出,Composite类型的对象可以包含其它Component类型的对象。换而言之,Composite类型对象可以含有其它的树枝(Composite)类型或树叶(Leaf)类型的对象。
合成模式的实现根据所实现接口的区别分为两种形式,分别称为安全模式和透明模式。合成模式可以不提供父对象的管理方法,但合成模式必须在合适的地方提供子对象的管理方法(诸如:add、remove、getChild等)。
透明方式
作为第一种选择,在Component里面声明所有的用来管理子类对象的方法,包括add()、remove(),以及getChild()方法。这样做的好处是所有的构件类都有相同的接口。在客户端看来,树叶类对象与合成类对象的区别起码在接口层次上消失了,客户端可以同等同的对待所有的对象。这就是透明形式的合成模式。
这个选择的缺点是不够安全,因为树叶类对象和合成类对象在本质上是有区别的。树叶类对象不可能有下一个层次的对象,因此add()、remove()以及getChild()方法没有意义,是在编译时期不会出错,而只会在运行时期才会出错。
安全方式
第二种选择是在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的做法,因为树叶类型的对象根本就没有管理子类对象的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。
这个选择的缺点是不够透明,因为树叶类和合成类将具有不同的接口。
这两个形式各有优缺点,需要根据软件的具体情况做出取舍决定。
安全式的合成模式实现: 只有composite有Add ,remove,delete等方法.
以下示例性代码演示了安全式的合成模式代码:
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
|
// Composite pattern -- Structural example
using System;
using System.Text;
using System.Collections;
// "Component"
abstract class Component
{
// Fields
protected string name;
// Constructors
public Component( string name )
{
this .name = name;
}
// Operation
public abstract void Display( int depth );
}
// "Composite"
class Composite : Component
{
// Fields
private ArrayList children = new ArrayList();
// Constructors
public Composite( string name ) : base( name ) {}
// Methods
public void Add( Component component )
{
children.Add( component );
}
public void Remove( Component component )
{
children.Remove( component );
}
public override void Display( int depth )
{
Console.WriteLine( new String( '-' , depth ) + name );
// Display each of the node's children
foreach( Component component in children )
component.Display( depth + 2 );
}
}
// "Leaf"
class Leaf : Component
{
// Constructors
public Leaf( string name ) : base( name ) {}
// Methods
public override void Display( int depth )
{
Console.WriteLine( new String( '-' , depth ) + name );
}
}
/// <summary>
/// Client test
/// </summary>
public class Client
{
public static void Main( string[] args )
{
// Create a tree structure
Composite root = new Composite( "root" );
root.Add( new Leaf( "Leaf A" ));
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.Add( new Leaf( "Leaf C" ));
// Add and remove a leaf
Leaf l = new Leaf( "Leaf D" );
root.Add( l );
root.Remove( l );
// Recursively display nodes
root.Display( 1 );
}
}
|
透明式的合成模式实现: 每个里都有add,remove等修改方法.
以下示例性代码演示了安全式的合成模式代码:
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
|
// Composite pattern -- Structural example
using System;
using System.Text;
using System.Collections;
// "Component"
abstract class Component
{
// Fields
protected string name;
// Constructors
public Component( string name )
{ this .name = name; }
// Methods
abstract public void Add(Component c);
abstract public void Remove( Component c );
abstract public void Display( int depth );
}
// "Composite"
class Composite : Component
{
// Fields
private ArrayList children = new ArrayList();
// Constructors
public Composite( string name ) : base( name ) {}
// Methods
public override void Add( Component component )
{ children.Add( component ); }
public override void Remove( Component component )
{ children.Remove( component ); }
public override void Display( int depth )
{
Console.WriteLine( new String( '-' , depth ) + name );
// Display each of the node's children
foreach( Component component in children )
component.Display( depth + 2 );
}
}
// "Leaf"
class Leaf : Component
{
// Constructors
public Leaf( string name ) : base( name ) {}
// Methods
public override void Add( Component c )
{ Console.WriteLine( "Cannot add to a leaf" ); }
public override void Remove( Component c )
{ Console.WriteLine( "Cannot remove from a leaf" ); }
public override void Display( int depth )
{ Console.WriteLine( new String( '-' , depth ) + name ); }
}
/// <summary>
/// Client test
/// </summary>
public class Client
{
public static void Main( string[] args )
{
// Create a tree structure
Composite root = new Composite( "root" );
root.Add( new Leaf( "Leaf A" ));
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.Add( new Leaf( "Leaf C" ));
// Add and remove a leaf
Leaf l = new Leaf( "Leaf D" );
root.Add( l );
root.Remove( l );
// Recursively display nodes
root.Display( 1 );
}
}
|
实例
再看看一个完整些的例子:
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
|
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Component
{
protected :
string name;
public :
Component(string name)
:name(name)
{ }
virtual void AddComponent(Component *component) { }
virtual void RemoveComponent(Component *component) { }
virtual void GetChild( int depth) { }
};
class Leaf: public Component
{
public :
Leaf(string name)
:Component(name)
{ }
void AddComponent(Component *component)
{
cout<< "Leaf can't add component" <<endl;
}
void RemoveComponent(Component *component)
{
cout<< "Leaf can't remove component" <<endl;
}
void GetChild( int depth)
{
string _tmpstring(depth, '-' );
cout<<_tmpstring<<name<<endl;
}
};
class Composite: public Component
{
private :
list<Component*> _componets;
public :
Composite(string name)
:Component(name)
{ }
void AddComponent(Component *component)
{
_componets.push_back(component);
}
void RemoveComponent(Component *component)
{
_componets. remove (component);
}
void GetChild( int depth)
{
string tmpstring (depth, '-' );
cout<<tmpstring<<name<<endl;
list<Component*>::iterator iter = _componets.begin();
for (; iter != _componets.end(); iter++)
{
(*iter)->GetChild(depth + 2);
}
}
};
int main()
{
Composite *root = new Composite( "root" );
Leaf *leaf1 = new Leaf( "leaf1" );
Leaf *leaf2 = new Leaf( "leaf2" );
root->AddComponent(leaf1);
root->AddComponent(leaf2);
Composite *lay2 = new Composite( "layer2" );
Leaf *leaf4 = new Leaf( "leaf4" );
lay2->AddComponent(leaf4);
Composite *lay1 = new Composite( "layer1" );
Leaf *leaf3 = new Leaf( "leaf3" );
lay1->AddComponent(leaf3);
lay1->AddComponent(lay2);
root->AddComponent(lay1);
root->GetChild(1);
cout<<endl;
lay1->GetChild(1);
cout<<endl;
lay2->GetChild(1);
delete root;
delete lay1;
delete lay2;
delete leaf1;
delete leaf2;
delete leaf3;
delete leaf4;
system ( "pause" );
return 0;
}
|
输出: