组合模式
意图
将对象组合成树型结构以标示部分-整体的层次结构,Composite使得用户对单个对象和组合对象的使用具有一致性。
效果
-
定义了包含基本对象和组合对象的类层次结构
-
简化客户代码
-
使得更容易增加新类型的组件
-
使你的设计变得更加一般化
代码示例
计算机和立体生组合音响这样的设备经常被组装成部分-整体层次结构或者是容器层次结构。例如,地盘可包含驱动装置和平版面,总线含有多个插件,机柜包括地盘、总线等。这种结构可以很自然地使用Composite模式进行模拟。
class Equipment{ public: virtual ~Equipment(); const char* Name(){ return _name;} virtual Watt Power(); virtual Currency NetPrice(); virtual Currency DiscountPrice(); virual void Add(Equipment*); virtual void Remove(Equipment*); virtual Iterator<Equipment*>* CreateIterator(); protected: Equipment(const char*); private: const char* _name; };
Equipment 声明一些操作返回一个设备的属性,例如它的能量消耗和价格。子类为指定的设备实现这些操作,Equipment还声明了一个CreateIterator操作,该操作为访问它的零件返回一个Iterator。 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; };
CompositeEquipment为方位和管理子设备定义了一些操作。操作Add和Remove从存储在_equipment成员变量中的设备列表中插入并删除设备。操作CreateIterator返回一个迭代器遍历这个列表。 NetPrice的缺省实现使用CreateIterator来累加子设备的实际价格
Curency 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(); };
我们可用相似的方式定义其他设备容器,如Cabinet和Bus。这样我们就得到了组装一台个人计算机所需的所有设备。
auto cabinet = new Cabinet("PC Cabinet"); auto chassis = new Chassis("PC Chassis"); cabinet->Add(chassis); auto 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;