Рассмотрим следующую ситуацию: у меня есть модуль C ++, который принимает XML-узел в качестве входных данных, преобразует его в некоторую другую структуру данных и возвращает результат.
Сейчас этот модуль реализован с использованием TinyXML , поэтому он принимает классы TinyXML в качестве входных данных (в частности, TiXmlNode).Это проблема, потому что она заставляет любого, кто хочет использовать мой модуль, использовать TinyXML для представления всего дерева документа.Например, если пользователь RapidXML хочет использовать мой модуль, он не сможет, потому что модуль ожидает узел TinyXML (и последующие дочерние узлы), а не узел RapidXML.Очевидно, что это плохой дизайн из-за плохого повторного использования.
Чтобы решить эту проблему, я готов применить принцип обращения зависимостей .Поэтому я проектирую этот чрезвычайно упрощенный 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, а не Node!Запись return new AdapterNode(node->FirstChild())
привела бы к явной утечке памяти, так как недавно выделенный AdapterNode никогда не получал бы delete
'd никем.
Несколько решений приходили мне в голову, чтобы решить эту проблему управления памятью, но большинствоиз них несколько некрасиво.Я прошу совета здесь: что бы вы предпочли в этой ситуации?