1、意图
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式(Composite)使得用户对单个对象和组合对象的使用具有一致性。
2、结构
3、参与者
Component:
为组合中的对象声明接口;
在适当的情况下,实现所有类共有接口的缺省行为;
声明一个接口用于访问和管理Component的子组件;
在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它(可选);
Leaf:
在组合中表示叶节点对象,叶节点没有子节点;
在组合中定义图元对象的行为;
Composite:
定义有子部件的那些部件的行为;
存储子部件;
在Component接口中实现与子部件有关的操作;
Client:
通过Component接口操纵组合部件的对象;
4、适用性
以下情况使用组合模式:
当想表示对象的部分-整体层次结构时;
当希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合就够中的所有对象;
5、代码示例
// Equipment类为在部分-整体层次结构中的所有设备定义了一个接口 // Equipment声明一些操作返回一个设备的属性,例如它的能量消耗和价格。 // 子类为指定的设备实现这些操作,Equipment还声明了一个CreateIterator操作,该操作为访问它的零件返回一个Iterator。 // 这个操作的缺省实现返回一个NullIterator,它在空集上叠代。 class Equipment { public: virtual ~Equipment (); const char* Name(){return_name;} virtual Watt Power(); virtual Currency NetPrice(); virtual Currency Discountprice(); virtual void Add(Equipment*); virtual void Remove(Equipment*); virtual Iterator<Equipment*>* CreateIterator(); protected: Equipment(const char*); private: const char*_name; };
// Equipment的子类包括表示磁盘驱动器、集成电路和开关的Leaf类: class FloppyDisk : public Equipment { public: FloppyDisk(const char*); virtual ~FloppyDisk(); virtual Watt Power(); virtual Currency Netprice(); virtual Currency DiscountPrice(); }; // CompositeEquipment是包含其他设备的基类,它也是Equipment的子类。 class CompositeEquipment : public Equipment { public: virtual ~CompositeEquipment (); virtual Watt Power(); virtual Currency NetPrice(); virtual Currency Discountprice(); virtual void Add(Equipment*); virtual void Remove(Equipment*); virtual Iterator<Equipment*>* CreateIterator(); protected: CompositeEquipment (const char*); private: List<Equipment*> _equipment; }; // NetPrice的缺省实现使用CreateIterator来累加子设备的实际价格 Currency CompositeEquipment::Netprice () { Iterator<Equipment*>* i = CreateIterator(); Currency total = 0; for (i->First(); !i->IsDone(); i->Next()) { total += i->CurrentItem()->NetPrice(); } delete i; return total; } // 现在我们将计算机的底盘表示为CompositeEquipment的子类Chassis。Chassis从CompositeEquipment继承了与子类有关的那些操作。 class Chassis : public CompositeEquipment { public: Chassis(const char*); virtual ~Chassis(); virtual Watt Power(); virtual Currency Netprice(); virtual Currency DiscountPrice(); };
// 我们可用相似的方式定义其他设备容器,如Cabineti和Bus。这样我们就得到了组装一台 //(非常简单)个人计算机所需的所有设备。 Cabinet* cabinet = new Cabinet("PC Cabinet"); Chassis* chassis = new Chassis("PC Chassis"); cabinet->Add(chassis); Bus* bus = new Bus("MCA Bus"); bus->Add(new Card("16Mbs Token Ring")); chassis->Add(bus); chassis->Add(new FloppyDisk("3.5in Floppy")); cout <"The net price is "<chassis->NetPrice()<<endl;
6、总结
组合模式是将对象组合成树形结构以表示对象的“部分-整体”层次结构。
多个基本对象可以组合成一个大的组合对象,这种操作是可重复可递归的,每个基本对象或组合对象都有一套统一的对外接口,供用户使用。组合模式使用户对单个对象和组合对象的使用具有一致性。
为保障后面组合的每一个组合对象都有相同的接口,组合模式中的Component类应该尽最大可能提供更多的共用接口。