深入剖析設(shè)計模式中的組合模式應(yīng)用及在C++中的實現(xiàn)
組合模式將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。C o m p o s i t e 使得用戶對單個對象和組合對象的使用具有一致性。
模式圖:

適用場景:
- 你想表示對象的部分-整體層次結(jié)構(gòu)。
- 你希望用戶忽略組合對象與單個對象的不同,用戶將統(tǒng)一地使用組合結(jié)構(gòu)中的所有對象。
舉例:
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)類型的對象。
合成模式的實現(xiàn)根據(jù)所實現(xiàn)接口的區(qū)別分為兩種形式,分別稱為安全模式和透明模式。合成模式可以不提供父對象的管理方法,但合成模式必須在合適的地方提供子對象的管理方法(諸如:add、remove、getChild等)。
透明方式
作為第一種選擇,在Component里面聲明所有的用來管理子類對象的方法,包括add()、remove(),以及getChild()方法。這樣做的好處是所有的構(gòu)件類都有相同的接口。在客戶端看來,樹葉類對象與合成類對象的區(qū)別起碼在接口層次上消失了,客戶端可以同等同的對待所有的對象。這就是透明形式的合成模式。
這個選擇的缺點是不夠安全,因為樹葉類對象和合成類對象在本質(zhì)上是有區(qū)別的。樹葉類對象不可能有下一個層次的對象,因此add()、remove()以及getChild()方法沒有意義,是在編譯時期不會出錯,而只會在運行時期才會出錯。
安全方式
第二種選擇是在Composite類里面聲明所有的用來管理子類對象的方法。這樣的做法是安全的做法,因為樹葉類型的對象根本就沒有管理子類對象的方法,因此,如果客戶端對樹葉類對象使用這些方法時,程序會在編譯時期出錯。
這個選擇的缺點是不夠透明,因為樹葉類和合成類將具有不同的接口。
這兩個形式各有優(yōu)缺點,需要根據(jù)軟件的具體情況做出取舍決定。
安全式的合成模式實現(xiàn): 只有composite有Add ,remove,delete等方法.
以下示例性代碼演示了安全式的合成模式代碼:
// 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 );
}
}
透明式的合成模式實現(xiàn): 每個里都有add,remove等修改方法.
以下示例性代碼演示了安全式的合成模式代碼:
// 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 );
}
}
實例
再看看一個完整些的例子:
#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;
}
輸出:

相關(guān)文章
C++ leetcode之刪除并獲得點數(shù)的示例代碼
這篇文章主要介紹了C++ leetcode之刪除并獲得點數(shù)的示例代碼,本文給大家分享問題解析及解決方案,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-05-05
輸入一個字符串,取出其中的整數(shù)(實現(xiàn)代碼)
輸入一個字符串,內(nèi)含所有數(shù)字和非數(shù)字字符。將其中連續(xù)的數(shù)字作為一個整數(shù),依次存放到一個數(shù)組中,統(tǒng)計共有多少個整數(shù),并輸出這些數(shù)2013-09-09
VC++實現(xiàn)View內(nèi)容保存為圖片的方法
這篇文章主要介紹了VC++實現(xiàn)View內(nèi)容保存為圖片的方法,涉及VC++中Bitmap類的save方法相關(guān)使用技巧,需要的朋友可以參考下2016-08-08
字典樹的基本知識及使用C語言的相關(guān)實現(xiàn)
這篇文章主要介紹了字典樹的基本知識及使用C語言的相關(guān)實現(xiàn),這也是ACM等計算機考試和競賽題目的基本知識,需要的朋友可以參考下2015-08-08

