Предположим, у меня есть два класса: FirstContainer
а также SecondContainer
Они содержат одну и ту же ссылку (передают в своем конструкторе) на класс ThirdContainer
,
FirstContainer и SecondContainer имеют следующие методы:
— addMemberToThirdContainer
— delMemberOfThirdContainer
— getThirdContainerMembers
Когда ThirdContainer будет изменен, я хочу, чтобы два других обновились с помощью getThirdContainerMembers()
, Для этого я использую образец наблюдателя / слушателя.
ThirdContainer
имеет список слушателей и метод: addNewListener
,
FirstContainer
а также SecondContainer
зарегистрироваться, выполнив: mThirdContainer.addNewListener(this);
Я не уверен, что это хороший способ сделать это, я новичок в ориентированном объекте.
Каковы мои другие возможности для достижения чего-то подобного?
Я не привязан ни к чему, что я сказал, просто здесь, потому что мне трудно объяснить, что я хочу сделать. Надеюсь это понятно.
Спасибо за помощь,
Лучший,
Редактировать:
Что бой с использованием предварительного объявления? Я мог бы сделать что-то вроде:
class ParentContainer {
public:
ParentContainer(ThirdContainer&)
: mFirstContainer(*this), mSecondContainer(*this) { };
~ParentContainer();
void addMemberToThirdContainer() {
mThirdContainer.addMember();
notify();
};
void delMemberOfThirdContainer() {
mThirdContainer.delMember();
notify();
};
private:
std::vec<int>& getMemberOfThirdContainer() {
return mThirdContainer.getMember();
};
void notify() {
auto vec = getMemberOfThirdContainer();
mFirstContainer.update(vec);
mSecondContainer.update(vec);
};
ThirdContainer& mThirdContainer;
FirstContainer mFirstContainer;
SecondContainer mSecondContainer;
};
Тогда в FirstContainer и SecondContainer что-то вроде:
class ParentContainer;
class FirstContainer {
public:
FirstContainer(ParentContainer&);
~FirstContainer();
void update(std::vector<int>& vec);
private:
ParentContainer& mParentContainer;
};
В FirstContainer и SecondContainer я получу доступ к ThirdContainer, выполнив:
mParentContainer.addMemberToThirdContainer и mParentContainer.DelMemberOfThirdContainer.
И я получу уведомление. Я имею в виду, я думаю ….
Если вам нравится использовать библиотеки, вы можете использовать любую библиотеку, которая предоставляет систему сигналов / слотов, например Boost или Qt.
Если вам не нравятся библиотеки, постарайтесь
Создать интерфейс (в C ++, просто абстрактный класс с чисто виртуальным методом, onModified
например:
class ThirdContainerListener {
public: virtual void onContainerModified() = 0;
// Virtual: is to make it overridable
// = 0: is the C++ way to say "abstract",
// which means this function MUST be overridden.
};
Делать vector
указателей на слушателей (чтобы быть в безопасности, попробуйте использовать умные указатели, такие как shared_ptr
) {Это идет в ThirdContainer}
vector<shared_ptr<ThirdContainerListener>> listeners;
Make (также внутри ThirdContainer), функция, которая добавляет слушателя, вот так
void addNewListener(shared_ptr<ThirdContainerListener> container) {
listeners.push_back(container); // Adds the pointer to the listeners
}
Скройте свой настоящий контейнер, вот так
private: vector<int> list;
Сделайте приватную функцию, которая вызывает всех слушателей, которые будут использоваться ЛОКАЛЬНО
private: void callAllListeners() {
// Traverse through all the listeners
for(shared_ptr<ThirdContainerListener> listener: listeners) {
// Call each one's overridden function
listener->onContainerModified();
}
}
Выставьте функции, которые изменяют ваш контейнер, они вызывают все слушатели, вот так
public: void addData(int d) {
list.push_back(d);
callAllListeners();
}
// Also you could make "removeDataByIndex", "addManyData", etc...
использование shared_ptr<ThirdContainer>
как в первом, так и во втором контейнере, чтобы гарантировать, что ваши классы не будут пропускать память или указывать ни на что (висящий указатель)
Когда
ThirdContainer
изменен, я хочу, чтобы два других обновились с помощьюgetThirdContainerMembers()
,
Зачем? Это не имеет особого смысла для меня. Или, по крайней мере, я не понимаю вашу мотивацию. Почему два контейнера не могут получить членов, когда они им действительно нужны, а не один раз при каждом обновлении? Или еще лучше — зачем вообще получать копию участников, когда вы можете просто держать членов в ThirdContainer
и повторять их там?
Теперь вы можете сказать: «Может быть, итератор становится недействительным во время такого доступа». Но это также проблема во время звонка getThirdContainerMembers()
,
ThirdContainer имеет список слушателей и метод: addNewListener.
Мне не нравится этот подход, и я бы посоветовал вам подумать, действительно ли вы хотите им следовать.
Я считаю, что он более подходит для интерпретируемых языков, которые имеют объекты с динамической типизацией, к которым вы можете добавлять или удалять функциональные возможности на лету, или, по крайней мере, у них есть механизмы, предоставляемые интерпретатором / виртуальной машиной, для наблюдения и самоанализа. С такими языками ваш ThirdContainer
не должен быть разработан заранее, чтобы поддержать слушателей.
С C ++, однако, вам придется навязать инкапсулированный дизайн ThirdContainer (или, по крайней мере, наследовать от существующего дизайна), чтобы он поддерживал слушателей). Но потом, в другой раз вам нужно будет прослушать какое-то другое событие, и вам снова нужно будет создать подкласс или изменить интерфейс ThirdContainer
— нет, я бы предпочел нет.
Вместо этого рассмотрите возможность того, чтобы кто-либо добавил элементы к ThirdContainer
нести ответственность также за обновление FirstContainer
а также SecondContainer
случаи, которые разделяют это; или вообще избегать обновлений.