Подтвердить что ты не робот

Заменить выражение о гигантском переключателе?

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

<html>
<head>
    <title>%title%</title>
</head>
<body bgcolor="%color%">
...etc.

В коде парсер находит их, вызывает эту функцию:

string getContent(const string& name)
{
    if (name == "title")
        return page->getTitle();
    else if (name == "color")
        return getBodyColor();
    ...etc.
}

а затем заменит исходный заполнитель на возвращаемое значение.

В реальном случае это не фиктивная веб-страница, и есть много (50+) разных заполнителей, которые могут произойти.

Мой код - С++, но я предполагаю, что эта проблема существует на любом языке. Думаю, это больше об алгоритмах и дизайне OO. Важно только то, что это должно быть скомпилировано, даже если бы я хотел, чтобы у меня не было никакого динамического /eval 'd кода.

Я, однако, о реализации шаблона Chain of Responsibility, но, похоже, он не улучшит ситуацию.

UPDATE: и я также обеспокоен этим комментарием в другом потоке. Должен ли я заботиться об этом?

4b9b3361

Ответ 1

Используйте словарь, который сопоставляет имена тегов с обработчиком тегов.

Ответ 3

Вы рассматривали XSLT? Это очень хорошо подходит для такого рода вещей. Я разработал систему управления контентом, которая сделала то же самое, и нашла XSLT очень эффективной. Парсер выполняет большую работу за вас.

UPDATE: комментарий Стивена поднимает важный момент: вы хотите, чтобы ваши шаблоны были действительными XHTML, если вы решите пойти по пути XSLT. Кроме того, я бы использовал другой разделитель для ваших токенов замены. Что-то менее вероятно происходит естественным образом. Я использовал #! PLACEHOLDER #! в моей CMS.

Ответ 4

Я объединю 3 идеи:

  • (от Steven Hugig): используйте метод factory, который дает вам другой класс для каждого селектора.
    • (от Нила Баттерворта): внутри factory используйте словарь, чтобы избавиться от большого switch(){}.
    • (мой): добавьте метод setup() к каждому классу обработчика, который добавляет себя (или новый экземпляр класса) в словарь.

пояснив немного:

  • создать абстрактный класс с static dict и методы регистрации экземпляра с помощью селекторной строки.
  • в каждом подклассе метод setup() регистрируется с помощью суперкласса "dict
  • метод factory - это немного больше, чем чтение словаря

Ответ 5

Вместо синтаксического анализа попробуйте просто прочитать шаблон в строке и затем просто выполнить замену.

fileContents = fileContents.Replace("%title%", page->getTitle());
fileContents = fileContents.Replace("%color%", getBodyColor());

Ответ 6

Как "Дядя" Боб Мартин упомянул в предыдущем подкасте с Джоэлом и Джеффом, почти все, что вы придумали, воспроизводить инструкцию большого коммутатора.

Если вам лучше реализовать одно из решений, выбранных выше, это прекрасно. Это может сделать ваш код более красивым, но под обложками он по сути эквивалентен.

Важно то, что есть только один экземпляр вашего большого оператора switch. Ваш оператор switch или словарь должны определить, какой класс обрабатывает этот тег, а затем последующие определения должны обрабатываться с использованием полиморфизма.