I have a large class called "System" (I'd like change "System" to "House"). The system contains different types of objects, such as window, and door. The different types of objects cannot be treated to be with a same base class. To build the system, I need to add those objects of different types one by one. And other methods such as delete one, clear all are also required to manage the system. I am comparing two ways to do it. One is to implement all the methods in the interface of the class System. The other is to expose the internal container of the objects and let the user to call the container's methods to do it. I think the first one should be better but there are so many similar code I need to write if I have many different types? Any better way to do it? Thanks.
class System
{
public:
AddDoor(Door);
DeleteDoor(Door);
DeleteAllDoors();
...
AddWindow(Window);
DeleteWindow(Window);
DeleteAllWindows();
...
......
private:
vector<Door> m_doors;
vector<Window> m_windows;
}
class System
{
public:
vector<Door>& Doors();
vector<Window>& Windows();
...
private:
vector<Door> m_doors;
vector<Window> m_windows;
}
Your implementation would look something like this:
class System {
public:
#if YOU_ARE_USING_C++11
template<typename... Args>
void Add(Args &&... args) {
GetContainer<T>().emplace_back(std::forward<Args>(args)...);
}
#else
template<typename T>
void Add(T const & t) {
GetContainer<T>().push_back(t);
}
#endif
template<typename T>
void Delete(T const & t) {
std::vector<T>::iterator position = std::find(GetContainer<T>().begin(), GetContainer<T>().end(), t);
GetContainer<T>().erase(position);
}
private:
template<typename T>
std::vector<T> & GetContainer();
};
template<>
std::vector<Doors> & System::GetContainer() {
return m_doors;
}
template<>
std::vector<Windows> & System::GetContainer() {
return m_windows;
}
Is something like this what you are looking for? It's kind of hard to tell what the "best" design is here without understanding your problem more.
That being said, sometimes, it may be appropriate to have a class as a public member, rather than just functions.
One key principle of object oriented design is "hide the implementation details" [something that you should consider even when NOT using object oriented design, of course].
In this case, it means that you should not expose that things are stored in a vector to the calling code. What would happen to the rest of your code if you decided that "Vector is no good for this type of thing, I need to use a map, or a list, or a tree, or ... It would mean changing at least SOME of the code, right? Which isn't a good thing, if you have lots of code.
So, your first idea is the better of the two presented here.
One thing that worries me a little bit tho' is the fact that the class is called "System". That can often mean that the class is a God Object - it contains everything and is everything. In general, a class should be as small and simple as it possibly can.
I'm not sure if you have a "God Object" or not, but the sign of it being called system (or manager) is a warning according to the Book "Effective C++" by Scott Meyers.
Aside from thte (very good) template solution, is to have a interface class for STORING and RETRIEVING the objects, and then let them have their separate lives elsewhere - you could even have separate containers for them, but still have a single set of code to add/remove objects of the interface type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With