Good day. I am facing a programming design task and am struggling with choosing the best approach for implementation due to lack of experience. I'd be glad to hear which practices, paradigms, or patterns are applicable to this case.
Problem Setting
You need to code, in C++98 standard, a Worker
class that can own abstract Tool
s. Tool
s can exist on their own, hence can be equipped and unequipped by workers; tools can't have more than one worker owner.
However, what makes this trickier is the fact lifetimes of these objects need to be managed accordingly:
- If a
Tool
is destroyed, it needs to get unequipped, since holding a pointer to a destroyed tool can lead to undefined behavior. - Similarly, if
Worker
is destroyed, theTool
should be disowned. - If a
Tool
is already given to aWorker
, giving it to anotherWorker
does remove theTool
from the original worker.
On top of that, suppose there's a class called Workshop
. Workshops must accept only workers who have an available tool of a certain pre-determined type (I decided to make Workshop
a template for a Tool
subtype).
If a workshop enrolls a worker, a random available tool of correct type gets associated with it and becomes unavailable to other enrollments. Again,
- If a
Worker
is destroyed, they leave the workshop. - If a
Tool
that aWorker
is using in aWorkshop
gets destroyed or assigned to another worker, theWorker
leaves the Workshop.
Questions
What is the best approach to this type of relationship?Currently, in order to implement the tool disowning upon destruction, I store Tool
pointers inside workers, and a Worker
pointer inside Tool
s. ~Tool()
calls a Worker
method that unequips it. However, since I want to make it possible to destroy the relationship from both classes, say, have a Tool::unset_owner()
and Worker::unequip(Tool*)
, both of them keep calling each other, resulting sometimes in infinite loops.
To add the Workshop
support, I decided to create a WorkshopBase
to hide its ToolType
template, and hold an std::map<Tool*, WorkshopBase*>
in Worker
to register tools and workshops. But, it further results in chains of calling double-sided methods that attempt to remove/insert pointers from each other.
However, I feel like I'm missing something essential and am violating some best practices for such one-to-many + many-to-many relationships. So my question is:
- How to avoid coupling in this case as much as possible?
- I've seen many posts that claim this is a bad practice. I wonder if there's a design pattern to address this? Do you think an event system with management classes would be a better fit?
- All in all, how to achieve my desired result gracefully?
Reminder: I'm looking for a C++98 solution. However, I would prefer to have answers with solutions with newer standards, with *_ptr<>
classes usage, maybe, as a footnote.
Aucun commentaire:
Enregistrer un commentaire