Многое зависит от ваших конкретных деталей приложения. Например, требуются ли name
и capacity
? Я собираюсь дать довольно общий ответ, который может быть немного излишним.
Предположения:
- Все вложенные свойства являются необязательными
- Есть много вложенных свойств, возможно различной глубины
Это предлагает две идеи: структурировать ваш интерпретатор как анализатор рекурсивного спуска и использовать своего рода конструктор для ваших объектов. В вашем конкретном примере у вас будет BuildingBuilder
, который выглядит примерно так (на Java):
public class BuildingBuilder {
public BuildingBuilder() { ... }
public BuildingBuilder setName(String name) { ... return this; }
public BuildingBuilder setCapacity(int capacity) { ... return this; }
...
public Building build() { ... }
}
Теперь, когда ваш парсер встречает элемент building
, используйте BuildingBuilder
для постройки здания. Затем добавьте этот объект в любой контекст, к которому применяется DSL (city.addBuilding(building)
).
Обратите внимание, что если name
и capacity
являются исчерпывающими и требуются всегда, вы можете просто создать здание, передав два параметра напрямую. Вы также можете построить здание и установить свойства напрямую, как встречается, вместо использования компоновщика (шаблон компоновщика удобен, когда у вас много свойств, и указанные свойства являются неизменяемыми и необязательными).
Если это не объектно-ориентированный контекст, вы в конечном итоге реализуете какую-то функцию buildBuilding, которая принимает текущий контекст и внутренний xml строительного элемента. По сути, вы создаете парсер рекурсивного спуска вручную с помощью библиотеки xml, обеспечивающей фактический анализ отдельных элементов.
Как бы вы ни реализовывали это, вы, вероятно, по достоинству оцените прямое семантическое сопоставление между элементами xml в вашем DSL и методами / объектами в вашем интерпретаторе.