I think this problem is best solved with a combination of Composite and Mediator .
Head up! I will show you another version of the mediator template that does not match the canonical version.
It is not the business of your compound structure to know whether an assistant has been called or not. You better do this with some kind of event handler.
Since you only have one helper, you can try like this:
class Helper { public: void callHelper() { std::cout << "Helper called" << std::endl; } }; class Mediator { private: std::map<std::string, std::vector<Helper>> subscribers; int updateLimit = -1; int currentUpdateCount = 0; void resetUpdateCount() { currentUpdateCount = 0; } public: Mediator(){} void subscribe(std::string evt, Helper helper) { subscribers[evt].push_back(helper); } void update(std::string evt) { for (auto& h: subscribers[evt]) { h.callHelper(); } } void setUpdateLimit(int i) { updateLimit = i; resetUpdateCount(); } void removeUpdateLimit() { updateLimit = -1; resetUpdateCount(); } int getUpdateLimit() { return updateLimit; } void updateLimited(std::string evt) { if (updateLimit < 0 || currentUpdateCount < updateLimit) { update(evt); currentUpdateCount++; } } }; int main(int argc, const char *argv[]) { Mediator m; Helper h1, h2; m.subscribe("bar", h1); m.setUpdateLimit(1);
Using it:
Mediator m; Helper h1, h2; m.subscribe("bar", h1); m.setUpdateLimit(1); // Will be called only once m.updateLimited("bar"); m.updateLimited("bar"); m.updateLimited("bar"); m.removeUpdateLimit();
So, here is what you do to integrate this composite structure. Remove the helper from your nodes, add Mediator to the base class:
struct Component { Component(Mediator& mediator) : m_helper(mediator) { } virtual void operation() = 0;
Using it:
Mediator m; Helper h; Composite c(m); Leaf1 l1(m), l2(m); c.add(l1); c.add(l2); m.subscribe(Component::updateEventName, h); m.setUpdateLimit(1);
IMPORTANT: This solution is suboptimal, it has some problems, for example, you need to pass a mediator instance for each node constructor, but this is just the initial idea for you.
Hope this helps!