组合模式

抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。在安全式的合成模式里,构件角色并不是定义出管理子对象的方法,这一定义由树枝构件对象给出。
树叶构件(Leaf)角色:树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。
树枝构件(Composite)角色:代表参加组合的有下级子对象的对象。树枝对象给出所有的管理子对象的方法,如add()、remove()、getChild()等。
Composite类型的对象可以包含其它Component类型的对象。换而言之,Composite类型对象可以含有其它的树枝(Composite)类型或树叶(Leaf)类型的对象。从名称可以看出树枝可以拥有树叶,树枝哟。
这样我们可以延伸如:Component-----公司,Leaf------部门,Composite-----分公司。
Component-----菜单,Leaf------子菜单,Composite-----主菜单。
Composite和Component是部分和整体的关系。
组合模式中,是将“Add和Remove等和对象容器相关的方法”定义在“表示抽象对象的Component类”中,还是将其定义在“表示对象容器的Composite类”中,是一个关乎“透明性”和“安全性”的两难问题,需要仔细权衡。这里有可能违背面向对象的“单一职责原则”,但是对于这种特殊结构,这又是必须付出的代价。
组合模式分透明方式,安全方式
透明方式:
树叶类对象和合成类对象对于外界没有区别,具备完全一致的行为接口。但是可以看见缺点是:leaf应该没有行为接口的(Add,Move等)。leaf等于多做了无用功。所以要下一种方式。
class Component { public: virtual void Add(Component c); virtual void Remove( Component c ); virtual void Display( int depth ); } class Composite : Component { public: // Methods void Add( Component component ) { children.Add( component ); } void Remove( Component component ) { children.Remove( component ); } void Display( int depth ) { } private: ArrayList children = new ArrayList(); } class Leaf : Component { public: // Methods void Add( Component component ) { children.Add( component ); } void Remove( Component component ) { children.Remove( component ); } void Display( int depth ) { } }
void Main() { 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 ); } }
安全方式:
在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的做法,因为树叶类型的对象根本就没有管理子类对象的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。这个选择的缺点是不够透明,因为树叶类和合成类将具有不同的接口。
class Component { public : virtual void Display( int depth ); } class Composite : Component { public: void Add( Component component ) { children.Add( component ); } void Remove( Component component ) { children.Remove( component ); } void Display( int depth ) { } private: ArrayList children = new ArrayList(); } class Leaf: Component { public: void Display( int depth ) { } }
main函数见上面。
在Composite 中保存了所有旗下的树叶树枝对象,这样调用display时,可以循环调用
Composite 模式通过和Decorator 模式有着类似的结构图,但是Composite 模式旨在构造类,而Decorator模式重在不生成子类即可给对象添加职责。Decorator模式重在修饰,而Composite 模式重在表示。
浙公网安备 33010602011771号