设计模式【八】:组合模式

设计模式【八】:组合模式

伪代码

伪代码引自Erich Gamma 等《Design Patterns》.

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;
};

class FloppyDisk: public Equiment{
public:
	FloppyDisk(const char*);
	virtual ~FloppyDisk();
	
	virtual Watt Power();
	virtual Currency NetPrice();
	virtual Currency DiscountPrice();
};

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;
};

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;
}

class Chassis:public CompositeEquipment{
};

class Cabinet:public CompositeEquipment{
};
//...

Cabinet* cabinet = new Cabinet("PC Cabinet");
Chassis* chassis = new Chassis("PC Chassis");
cabinet->Add(chassis);

Bus* bus = new Bus("Bus");
bus->Add(new Card("16mb card"));

chassis->Add(bus);
chassis->Add(new FloppyDisk("3.5in disk"));

cout<<"The total price is "<<chassis->NetPrice()<<endl;

优缺点

优点
  • 定义元对象和组合对象,并使对象可以递归地被组织起来。
  • 简化使用者的操作。使用者可以对组合对象和元对象一致对待。比如伪代码中计算总价格的函数在组合对象内部递归实现。
  • 易于添加组合对象的组件。
缺点
  • 增大对组合对象的管理难度。因为在组合模式下对象的组件可以动态增删,所以不应依赖类名来判断组合对象的具体构成,确定对象具体构成需要在运行时动态检查。

何时使用

  • 需要组织组合对象(往往是树形结构)。
  • 需要使用者忽略组合对象与元对象的区别。

实现时技巧

  • 可构造子组件对父组件的隐式引用,比如在子组件的构造函数中添加一个指向父组件的指针。这样可以方便在对象树上的遍历。
  • 慎用共享的子组件。复用组件当然可以简化程序,但这会导致子组件可能有多个父组件。如果在子组件内维护一个指针链表可以管理这种情况,但这样反而使程序复杂。
  • 对象接口应当设计为各组件的并集。我们可以将叶子组件(元组件)视为不会返回子组件的一般组件,这样有助于简化接口设计。当然,这是灵活性与安全性的trade off,如果我们在叶子组件里声明全部的操作(包括对其子组件的操作,只不过返回null),其实是牺牲安全性来换取灵活性。
  • 可能需要对子组件排序。
  • 如果需要频繁遍历组件树,可缓存最近遍历的若干子组件等等。
  • 如果实现语言没有垃圾回收机制,需要考虑释放内存。一般父组件delete时需要delete它所有的子组件。
  • 总之,由于其树型组织结构,其注意事项有很多是与数据结构课上学的树有所对应。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值