哪个C ++模式用于允许扩展其类的库?

时间:2016-02-15 15:02:34

标签: c++ design-patterns polymorphism

我正在尝试将一些代码从我的C ++模拟软件拆分到库中,因此可以更灵活地使用它。模拟基于Lattice,由许多Node组成,其中包含指向其Neighbor的指针列表。虽然邻居也是节点,但我希望在*Node指针周围有一个小的包装类,以便实现其他逻辑/字段(例如,bool is_neares_neighbor左右。

我的类架构因此看起来像这样:

class Lattice {
private:
    vector<Node> _nodes;
};

class Node {
private:
    vector<Neighbor> _neighbors;
};

class Neighbor {
private:
    Node * _node;
};

到目前为止,这么好。现在,我希望我的库能够处理所有与格相关的逻辑,但没有别的。但是,在某个项目中使用库时,这三个类(LatticeNodeNeighbor)将包含更多逻辑和字段。因此,用户应该能够从这些类继承并实现他/她的自定义内容,而库仍然处理所有必需的与格相关的逻辑。

建议的方法是什么?模板是否合适?在模板化的情况下,我的类层次结构将如下所示:

template<class N>
class Lattice {
private:
    vector<N> _nodes;
};

template<class NN>
class Node {
private:
    vector<NN> _neighbors;
};

template<class N>
class Neighbor {
private:
    N * _node;
};

正如您所看到的,NodeNeighbor都需要知道彼此的类型,这是一个循环条件,我不知道如何处理这里。此外,整个库必须存在于头文件中。

如何在C ++世界中以最优雅的方式处理这些情况?

2 个答案:

答案 0 :(得分:1)

我在想你希望模板类型是格子库不知道或不关心的“其他类型”。因此,不是让用户从Node派生,而是使用模板&lt; class t_data&gt;为你所有的课程。

你说自己,邻居是一个节点,所以你应该能够根据Node&lt; t_data&gt;来定义所有内容。

您还应该考虑如何构建晶格,以及如何返回有关它的信息。这是一个例子,我假设你通过让格子类创建节点来创建格子,并且可以选择在创建时将它们连接到现有节点。

#include <vector>
#include <memory>

template<class t_data>
class SetOfNodes;

template<class t_data>
class Node {
public:
    Node(t_data value, SetOfNodes neighbors) : _data(value), _neighbors(neighbors) {}
    is_nearest_neighbor(const Node &other){
        // is other in _neighbors?
        // is other the closest neighbor?
        return false;
    }
private:
    t_data _data;
    SetOfNodes _neighbors;
};

template<class t_data>
class SetOfNodes {
public:
    std::vector<std::shared_ptr<Node<t_data>>> _nodes;
};

template<class t_data>
class Lattice {
public:
    SetOfNodes get_all_nodes();
    void create_new_node(SetOfNodes neighbors);
private:
    SetOfNodes _nodes;
};

我真的不了解Neighbor,因为要么是Node,要么它涉及两个节点,所以我会单独留下它。

答案 1 :(得分:0)

我建议你使用复合/访客模式的组合:

  • Composite将帮助您定义Lattice / Node / Neighbor / Custom_User_Node_Derived类的层次结构,可以统一处理(无论内容是什么)
  • 访问者将帮助您抓取层次结构并封装您的莱迪思/节点/邻居类的逻辑,并让用户定义您实际无法实际预测的新操作。

当您想要扩展您无法控制的库(或类集)时,这是一种特别推荐的方法。根据我的理解,这是您希望用户能够做到的事情之一。