2016-11-25 15 views
2

Мне нужно разобрать XML и создать объекты на C++, которые соответствуют элементам XML, а также упаковать атрибуты элементов XML в эти объекты как свойства. Элементы/атрибуты XML и соответствующие классы/свойства C++ наследуются от базового объекта, который имеет свойства, общие с производными объектами.Полиморфизм или словарь свойств?

Я думал использовать базовый класс для общих свойств, а производные классы должны были только определять свойства объекта. Тем не менее, кто-то сказал мне, что использование стандартного полиморфизма здесь не очень хорошо, потому что решение не является достаточно общим - добавление/изменение атрибутов в XML потребует добавления/изменения соответствующих свойств к классам C++, что требует слишком большого количества кода , Лучше и более абстрактным решением было бы поместить словарь атрибутов в базовый класс и получить доступ к отдельным свойствам, выполнив поиск в словаре. Я хотел спросить сообщество, лучше ли это предложение для производственного кода.

Ниже приведен пример, где транспортное средство является базовым объектом и различными типами автомобилей, унаследовавшими его. Автомобиль объект имеет name и weight свойства, которые являются общими для всех автомобилей. Вот фрагмент образца XML:

<car name="Toyota" weight="3500" passengers="4" /> 
<boat name="Yamaha" weight="3700" draft="16" /> 

Базовый класс:

class vehicle { 
    public: 
    string name; 
    string weight; 
}; 

Производные классы:

class car : public vehicle { 
    public: 
    string passengers; 
}; 

class boat : public vehicle { 
    public: 
    string draft; 
}; 

Теперь, когда мой анализатор находит машину и лодочные элементы I инстанцирует:

boat *b = new boat(); 
car *c = new car(); 

Для Лодка Я могу получить доступ ко всем участникам просто как b->name, b->weight и b->draft. После того, как объекты C++ создаются из XML, мы выполняем всю совокупность объектно-ориентированной работы над каждым свойством, поэтому целью является не просто просто загрузить XML в программу.

Альтернативный подход:

#define TAG_XML_ATTRIBUTE_NAME    "name" 
#define TAG_XML_ATTRIBUTE_WEIGHT   "weight" 
#define TAG_XML_ATTRIBUTE_PASSENGERS  "passengers" 
#define TAG_XML_ATTRIBUTE_DRAFT    "draft" 
. . . 

class vehicle { 
    public: 
    map<string, string> arguments; 

    // Get argument by name searching the arguments dictionary. 
    string GetArgumentOrEmpty(const string& argumentName); 
}; 

class car : public vehicle { 
    public: // All propeties are in the base class dictionary. 
}; 

class boat : public vehicle { 
    public: // All propeties are in the base class dictionary. 
}; 

Все производные классы имеют arguments карту; чтобы получить значение свойства, мы сканируем словарь, чтобы найти свойство по имени, а затем прочитать его значение, например. GetArgumentOrEmpty(TAG_XML_ATTRIBUTE_WEIGHT). В наши дни процессоры быстрые, поэтому поиск словаря не будет заметным, влияя на производительность. Пространство имен элементов/атрибутов происходит от структурированных (как членов класса) до flat (в виде #define list), но все они будут находиться в одном месте. Код более абстрактный; хотя код обработки объекта становится более сложным из-за дополнительной косвенности, ему не нужно изменять, если имя атрибута изменяется; например если passengers в изменениях XML в people, то #define будет выглядеть немного неудобно, но код, который использует его не придется менять:

#define TAG_XML_ATTRIBUTE_PASSENGERS  "people" 

ли на основе словаря метод доступа свойство настоящего достаточно пользы использовать его для производственного кода вместо использования обычных свойств класса? Если да, то только для этого конкретного случая XML-разбора или для замены полиморфизма поиском словаря и замены свойств класса с помощью имен строк является лучшей идеей в целом?

ответ

1

Словарь подход, основанный действительно имеет несколько преимуществ:

  • Это легко добавлять новые новые свойства класса/объекта.
  • Код загрузки/сохранения/создания объекта будет довольно общим.
  • Это можно сделать свойство, которые принадлежат к классам полностью настраиваемым
  • На самом деле какая-то игра кодирование экспертов, таким как Mike McShaffryGame Coding Complete») выступает за использование такого рода архитектура „Component“ для представления игры актеров, а не глубокие иерархии наследования, которые сложнее поддерживать и обогащать.

Есть несколько неудобств, а также:

  • Конкретный код обработки класса будет завален добытчиками
  • Этот код будет в значительной степени зависеть от свойств нейминга, что делает конфигурируемость менее легко.
  • Было бы легко получить ошибки в системе из-за незаметных опечаток: компилятор не заметил бы эти несоответствия, поскольку это всего лишь литерные данные.

Так что вам нужно сделать трудный выбор. Мой совет:

  • Если у вас есть сложный код обработки, зависящий от класса, тогда это будет ошибка, склонная придерживаться вашего первоначального подхода. Преимущество компилятора, зная переменные-члены, которые вы используете, будет гарантией надежности.
  • Если у вас есть только пара подпрограмм, зависящих от класса, и если свойства в основном описательны и обрабатываются подобным образом, то имеет смысл сделать подход к карте
  • , если вам нужна легко расширяемая и конфигурируемая структура объекта , второй подход также будет более гибким подходом.

Если вы идете на карту, пара мыслей:

  • вы могли бы думать о словаре между именем внешней собственности и внутренним целым, эквивалентным обозначением. Это ускорило бы карту, избегая больших затрат на обработку строк.
  • из них можно было бы использовать unordered_map, чтобы избежать слишком большого сравнения строк.
+0

Christophe, не могли бы вы закончить свою мысль? «На самом деле некоторые эксперты по кодированию игр, такие как ...» - подробности здесь чрезвычайно ценны. – sun2sirius

+0

@ sun2sirius Извините, предложение было сокращено и потеряно во время написания. Я редактировал для завершения предложения. – Christophe