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

GOF Composite Design Pattern CompositeObject::Remove Recursive Implementation in C++

本文关键字:递归 实现 C++ 删除 复合 设计模式 CompositeObject GOF      更新时间:2023-10-16

这是我在代码审查网站中提出的问题的一部分

用现代C++实现GOF复合设计模式

该帖子有关于它的完整信息/实施,但我在这里发布这个问题是为了了解以下信息:

How to implement CompositeEquipment::Remove?.

根据我的理解,它应该在客户端调用的所有复合对象和recursively all its child objects which can also be of composite type中进行递归搜索。只是从上面的实现中举例说明,如果客户端将写为cabinet->Remove(bus);它不会移除总线对象,因为它是CCD_ 3对象的子对象。这对我来说似乎是不正确的。然而,我不能以递归搜索子对象本身是否为复合对象的方式来实现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. 在基类中提供一个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);
               }
            }
        }
    }
    

关于名字。。。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);
               }
            }
        }
    }