Отображение полиморфных классов - PullRequest
4 голосов
/ 26 декабря 2008

У меня есть приложение с интерфейсом командной строки, к которому я добавляю графический интерфейс. Часто возникает ситуация, когда у меня есть список объектов, которые наследуются от одного класса и должны отображаться в списке, но каждый подкласс имеет немного другой способ отображения.

Не желая иметь повсюду гигантские операторы switch, использующие отражение / RTTI для отображения, каждый класс знает, как вернуть свою собственную итоговую строку, которая затем отображается в списке:

int position = 0;
for (vector<DisplayableObject>::const_iterator iDisp = listToDisplay.begin(); iDisp != listToDisplay.end(); ++iDisp)
    cout << ++position << ". " << iDisp->GetSummary();

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

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

Есть ли какая-то техника, которую я могу использовать, чтобы отделить этот код GUI от объектов данных, не прибегая к RTTI и операторам switch? Было бы неплохо иметь возможность также использовать функции GetSummary.

В идеале я бы мог иметь иерархию классов отображения, которая могла бы брать класс данных и отображать его на основе типа времени выполнения вместо типа времени компиляции:

shared_ptr<Displayer> displayer = new ConsoleDisplayer(); 
// or new GUIDisplayer()

for (vector<DisplayableObject>::const_iterator iDisp = listToDisplay.begin(); iDisp != listToDisplay.end(); ++iDisp)
    displayer->Display(*iDisp);

1 Ответ

6 голосов
/ 26 декабря 2008

Я не думаю, что это решит вашу проблему отсутствия необходимости писать код, но вы должны быть в состоянии абстрагировать логику GUI от объектов данных.

Посмотрите на шаблон посетителя (http://en.wikipedia.org/wiki/Visitor_pattern), он позволит вам добавить код к существующему объекту без изменения самого объекта. Вы также можете изменить посетителя на основе платформы.

...