我使用这种风格的地方是我需要实现一个既易于使用又易于维护的通用图形库
过了一会儿,我有了这个设计:
GraphContainer,Edge,Node 的抽象类:
template < class T1,class T2>
class GraphAbstractContainer
{
public:
using Node = T1;
using Edge = T2;
virtual std::list<Node> getConnectedNodes(const Node& node)const = 0;
virtual Node addNode(const Node&) = 0;
//...
};
class GraphAbstracthNode
{
public:
virtual uint32_t getId() const = 0;
virtual void setID(uint32_t id)=0;
//..
};
template<class T>
class GraphAbstractEdge
{
public:
using Node = T;
//GraphAbstractEdge(){}
virtual Node firstNode() const = 0;
virtual Node secondNode() const = 0;
virtual void setFirstNode(const Node& node) = 0;
virtual void setSecondNode(const Node& node) = 0;
//...
};
然后我通过直接从模板参数继承来添加 Adj_List 和 Adj Matrix 实现。
例如,我的 Adj 列表类看起来像这样:
template<class T1 = GraphAbstractContainer<GraphAdjNode,
GraphAdjEdge>>
class GraphAdjListContainer : public T1
{
public:
using Node = typename T1::Node;
using Edge = typename T1::Edge;
//return connected Nodes
virtual std::list<Node> getConnectedNodes(const Node& node) const
{
//..
}
//..
};
};
template<class T>
class GraphAdjNode : public T
{
public:
//implementing abstract class methods...
};
template<class T>
class GraphAdjEdge : public T
{
public:
//...
};
My Graph 类也直接从模板继承:
template<class GraphContainer=GraphAdjListContainer<>>
class Graph :public GraphContainer
{
public:
using Node = typename GraphContainer::Node;
using Edge = typename GraphContainer::Edge;
//...
}
这种设计模式的一个优点是您可以通过从抽象类继承并填充模板参数来简单地更改整个类的底层内容。
例如,我通过简单地这样做来定义 Trie 数据结构:
class TrieNode :public GraphAdjNode
{
public:
//...
std::string word_;
};
class Trie
{
public:
using Graph = Graph < ecv::GraphAdjListContainer<TrieNode, ecv::GraphAdjListEdge<TrieNode>>>;
using Node = Graph::Node;
using Edge = Graph::Edge;
void addWord(wstring word);
//...
private:
Graph graph_;
}