这是我在codereview网站上提出的问题的问题:
GOF Composite Design Pattern Implementation Using Modern C++
该帖子有关于它的完整信息/实施,但在这里我发布此问题以了解以下信息:
How to implement CompositeEquipment::Remove?.
根据我的理解,它应该在客户端调用的所有复合对象和recursively all its child objects which can also be of composite type
中进行递归搜索。仅从上面的实现来说明,如果客户端写为cabinet->Remove(bus)
;它不会删除总线对象,因为它是chassis
对象的子对象。这似乎对我不正确。但是我无法以这样的方式实现CompositeEquipment::Remove
,即如果子对象本身是复合的,它会递归搜索。
到目前为止,我已经开始使用以下实现,它只搜索客户端参与Remove
方法的复合对象。
//To find out whether items are in the composite objects
class Name_Equal {
private:
Equipment::EquipmentSmartPtr val;
public:
Name_Equal(const Equipment::EquipmentSmartPtr& v) :val(v) { }
bool operator()(const Equipment::EquipmentSmartPtr& x) const {
return (x->Name() == val->Name());
}
};
void CompositeEquipment::Remove(EquipmentSmartPtr entry) {
find_equipment(_equipment, entry);
}
void CompositeEquipment::find_equipment(std::vector<EquipmentSmartPtr>& vec,
EquipmentSmartPtr& entry){
Name_Equal eq(entry);
auto itrpos = std::find_if(std::begin(vec), std::end(vec), eq);
if (itrpos != std::end(vec)) {
vec.erase(itrpos);
}
}
如果有任何其他信息或完整代码需要在此发布,请告诉我。
答案 0 :(得分:1)
有两种选择:
在基类中提供virtual
函数Remove
并使其成为noop实现。然后再向CompositeEquipment::find_equipment
添加几行。
void CompositeEquipment::find_equipment(std::vector<EquipmentSmartPtr>& vec,
EquipmentSmartPtr& entry){
Name_Equal eq(entry);
auto itrpos = std::find_if(std::begin(vec), std::end(vec), eq);
if (itrpos != std::end(vec)) {
vec.erase(itrpos);
} else {
for ( EquipmentSmartPtr sptr : vec )
{
sptr->Remove(entry);
}
}
}
使用dynamic_cast
确定复合材料的项目是否也是复合材料。如果是,请在其上调用Remove
。我更喜欢这个选项。
void CompositeEquipment::find_equipment(std::vector<EquipmentSmartPtr>& vec,
EquipmentSmartPtr& entry){
Name_Equal eq(entry);
auto itrpos = std::find_if(std::begin(vec), std::end(vec), eq);
if (itrpos != std::end(vec)) {
vec.erase(itrpos);
} else {
for ( EquipmentSmartPtr sptr : vec )
{
Equipment* ptr = dynamic_cast<Equipment*>(sptr.get());
if ( ptr )
{
ptr->Remove(entry);
}
}
}
}
关于名字...... find_equipment
似乎是一个奇怪的名称。我会把整件事放在Remove
。
void CompositeEquipment::Remove(EquipmentSmartPtr& entry){
std::vector<EquipmentSmartPtr>& vec = _equipment;
Name_Equal eq(entry);
auto itrpos = std::find_if(std::begin(vec), std::end(vec), eq);
if (itrpos != std::end(vec)) {
vec.erase(itrpos);
} else {
for ( EquipmentSmartPtr sptr : vec )
{
Equipment* ptr = dynamic_cast<Equipment*>(sptr.get());
if ( ptr )
{
ptr->Remove(entry);
}
}
}
}