Это часть вопроса из моего вопроса, заданного в Просмотр Кода Веб-сайт:
GOF Составная реализация шаблона проектирования с использованием современного 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);
}
}
Пожалуйста, дайте мне знать, если какая-либо дополнительная информация или полный код необходимо опубликовать здесь.
Есть два варианта:
Обеспечить 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);
}
}
}
}