深入剖析设计模式中的组合模式应用及在C++中的实现

2020-01-06 14:46:51王冬梅


可以看出,Composite类型的对象可以包含其它Component类型的对象。换而言之,Composite类型对象可以含有其它的树枝(Composite)类型或树叶(Leaf)类型的对象。

合成模式的实现根据所实现接口的区别分为两种形式,分别称为安全模式和透明模式。合成模式可以不提供父对象的管理方法,但合成模式必须在合适的地方提供子对象的管理方法(诸如:add、remove、getChild等)。

透明方式

 

作为第一种选择,在Component里面声明所有的用来管理子类对象的方法,包括add()、remove(),以及getChild()方法。这样做的好处是所有的构件类都有相同的接口。在客户端看来,树叶类对象与合成类对象的区别起码在接口层次上消失了,客户端可以同等同的对待所有的对象。这就是透明形式的合成模式。

这个选择的缺点是不够安全,因为树叶类对象和合成类对象在本质上是有区别的。树叶类对象不可能有下一个层次的对象,因此add()、remove()以及getChild()方法没有意义,是在编译时期不会出错,而只会在运行时期才会出错。

安全方式

第二种选择是在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的做法,因为树叶类型的对象根本就没有管理子类对象的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。

这个选择的缺点是不够透明,因为树叶类和合成类将具有不同的接口。

这两个形式各有优缺点,需要根据软件的具体情况做出取舍决定。

安全式的合成模式实现: 只有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 );
 }
}