#cpp #qt #архитектура
Сразу прошу прощения за такой заголовок, я просто не знаю, как в двух словах описать
проблему.
Ситуация следующая. Допустим, есть некий класс "рабочее место":
class Workplace{
};
и класс "работник", который знает, к какому рабочему месту он относится:
class Worker{
Workplace *_workplace;
public:
explicit Worker(Workplace *workplace):
_workplace(workplace)
{}
};
В процессе разработки оказалось, что было бы хорошо, если бы Workplace знал список
всех, кто на нем работает. Наподобие того, как QObject знает список всех своих детей.
Сделано это было примерно так:
class Worker;
class Workplace{
std::vector _workers;
public:
const std::vector& workers() const{
return _workers;
}
private:
friend class Worker;
void _add(Worker *worker){
_workers.push_back(worker);
}
void _remove(Worker *worker){
_workers.erase(std::remove(_workers.begin(), _workers.end(), worker), _workers.end());
}
};
class Worker{
Workplace *_workplace;
public:
explicit Worker(Workplace *workplace)
{
setWorkplace(workplace);
}
void setWorkplace(Workplace *workplace){
if(_workplace == workplace){
return;
}
if(_workplace){
_workplace->_remove(this);
}
if(workplace){
workplace->_add(this);
}
_workplace = workplace;
}
~Worker(){
setWorkplace(0);
}
};
Если в двух словах: каждый раз, когда у работника меняется рабочее место, он сообщает
старому, что он больше там не работает, и новому - что он там работает.
В таком небольшом примере все вроде бы работает как надо. Однако классов у меня гораздо
больше, и код получился весьма запутанным. Может, кто-нибудь знает более элегантное
решение этой проблемы? Ну или хотя бы её название, если оно есть.
PS: Есть еще класс, который содержит в себе весь этот зоопарк, назовем его Company:
class Company{
std::vector _workers;
std::vector _workplaces;
//...
};
Теоретически он может выступать в роли посредника, однако я пока не придумал как
это может мне помочь.
Ответы
Ответ 1
Может, кто-нибудь знает более элегантное решение этой проблемы? Ну или хотя бы её название, если оно есть. Задание на создание графа, или фактически стирание классов чтоб не писать много. Пишешь один раз class Container{ Container * children; public: explicit Container(Container* children): //и т.п. {} }; потом все утилиты для контейнера. пишешь один раз графическое представление Container вместе с его перетаксиванием. Потом например class Company{ std::vector_workers; std::vector _workplaces; ... Ответ 2
Ну, можно, например, держать одну большую таблицу с записями "работник/рабочее место" и при необходимости выполнять поиск в ней. Для небольшого количества записей - ну, там, тысячи - обычный вектор пар будет вполне адекватен. Если гораздо больше - можно подумать об ассоциативных контейнерах (типа, multimap может оказаться подходящим решением). Если скорость критична - тогда надо жертвовать простотой и в каждом классе иметь соответствующие поля и при смене выполнять обновления - при большой запутанности, возможно, каскадные. Задача скорее из БД :)
Комментариев нет:
Отправить комментарий