GOF复合设计模式CompositeObject ::删除C ++中的递归实现

时间:2014-10-26 04:06:03

标签: c++ design-patterns c++11 recursion composite

这是我在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);
    }
}

如果有任何其他信息或完整代码需要在此发布,请告诉我。

1 个答案:

答案 0 :(得分:1)

有两种选择:

  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);
            }
        }
    }
    
  2. 使用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);
               }
            }
        }
    }
    
  3. 关于名字...... 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);
                   }
                }
            }
        }