3

我有一个名为“System”的大类(我想将“System”更改为“House”)。该系统包含不同类型的对象,例如窗户和门。不同类型的对象不能被视为具有相同的基类。为了构建系统,我需要将这些不同类型的对象一一添加。而其他方法,如删除一个,清除所有也需要管理系统。我正在比较两种方法来做到这一点。一是实现类System的接口中的所有方法。另一种是暴露对象的内部容器,让用户调用容器的方法来做。我认为第一个应该更好,但是如果我有很多不同的类型,我需要编写很多类似的代码吗?有什么更好的方法吗?谢谢。

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;
}
4

2 回答 2

2

面向对象设计的一个关键原则是“隐藏实现细节”[当然,即使不使用面向对象设计,您也应该考虑这一点]。

在这种情况下,这意味着您不应将存储在向量中的内容暴露给调用代码。如果您认为“矢量不适用于这种类型的事情,我需要使用地图、列表、树或......这意味着至少要更改一些代码,对吗?如果你有很多代码,这不是一件好事。

所以,你的第一个想法是这里提出的两个更好的想法。

让我有点担心的一件事是这个类被称为“系统”。这通常意味着该类是一个上帝对象——它包含一切并且是一切。一般来说,一个类应该尽可能的小和简单。

我不确定您是否有“上帝对象”,但根据 Scott Meyers 的“有效 C++”一书,它被称为系统(或管理器)的标志是一个警告。

除了(非常好的)模板解决方案之外,还有一个用于存储和检索对象的接口类,然后让它们在其他地方有自己的独立生活——您甚至可以为它们提供单独的容器,但仍然只有一组代码添加/删除接口类型的对象。

于 2012-12-27T23:19:58.953 回答
2

您的实现将如下所示:

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;
}

你正在寻找这样的东西吗?如果不进一步了解您的问题,很难说出这里的“最佳”设计是什么。

话虽如此,有时将类作为公共成员可能是合适的,而不仅仅是函数。

于 2012-12-27T23:14:21.620 回答