【发布时间】:2011-05-24 19:32:01
【问题描述】:
考虑以下情况:我有一个 C++ 模块,它以 XML 节点作为输入,将其转换为其他数据结构,然后返回结果。
现在这个模块是使用TinyXML 实现的,所以它把TinyXML 类作为输入(特别是一个TiXmlNode)。这是一个问题,因为它迫使任何想要使用我的模块的人使用 TinyXML 来表示整个文档树。例如,如果RapidXML 用户想要使用我的模块,他将无法使用,因为该模块需要一个 TinyXML 节点(以及后续的子节点),而不是 RapidXML 节点。显然,这是一个糟糕的设计,因为可重用性差。
为了解决这个问题,我愿意申请Dependency inversion principle。所以我设计了这个极其简化的、类似 DOM 的界面:
class Node
{
public:
enum Type { TYPE_ELEMENT, TYPE_TEXT };
virtual ~Node() { }
virtual Type getType() = 0;
virtual Node* getParentNode() = 0;
virtual Node* getPreviousSibling() = 0;
virtual Node* getNextSibling() = 0;
};
class Element : public Node
{
public:
virtual ~Element() { }
virtual const char* getName() = 0;
virtual Node* getFirstChild() = 0;
virtual Node* getLastChild() = 0;
virtual const char* getAttribute(const char* name) = 0;
};
class Text : public Node
{
public:
virtual ~Text() { }
virtual const char* getText() = 0;
};
然后我使用Adapter 设计模式实现这些接口,包装等效的TinyXML 类。或者至少我尝试:
class AdapterNode : public Node
{
private:
const TiXmlNode& node;
public:
AdapterNode(const TiXmlNode& node) : node(node) { }
virtual Node* getFirstChild() { Uh... oh, wait.
你可以看到我正在进入一个内存管理的噩梦:我应该在这里返回一个预先存在的、已经分配的节点。事实上,我有一个预先存在的、已分配的 TiXmlNode(可通过node->FirstChild() 访问),但这是一个 TiXmlNode,而不是一个节点!写入return new AdapterNode(node->FirstChild()) 会导致明显的内存泄漏,因为新分配的AdapterNode 永远不会被任何人获得delete。
我想到了一些解决这个内存管理问题的解决方案,但大多数都有些难看。我在这里寻求建议:对于这种情况,您首选的解决方案是什么?
【问题讨论】:
标签: c++ oop memory-management inversion-of-control adapter