Привет. Паттерн стратегия ужасен!
Есть абстрактный класс CItem. От него есть производные CItemChild1, CItemChild2 - которые хранят различные наборы данных.
Ниже псевдокод, не ругайтесь
class CItem {
int my_rtti;
int commonVal;
};
class CItemChild1 : public CItem {
int my_rtti = 1;
int val11;
int val12;
};
class CItemChild2 : public CItem {
int my_rtti = 2;
int val22;
int val23;
int val24;
};
Есть задача отображать данные из производного от класса CItem (CItemChild1 или CItemChild2). Отображение зависит от конкретного класса.
Я на главный виджет добавил QStackWidget (показывает одновременно только один виджет) и в него поместил два виджета (widget1 и widget2) для отображения данных.
class QMyWidget : public QWidget {
virtual void load(CItem *_itm) = 0;
};
class CWidget1 : public QMyWidget {
virtual void load(CItem *_itm) { ... };
};
class CWidget2 : public QMyWidget {
virtual void load(CItem *_itm) { ... };
};
class MainWidget {
CWidget1 *widget1;
CWidget2 *widget2;
}
// отображение данных полученных откуда-нибудь
void MainWidget::show(CItem *_itm)
{
if (_itm->my_rtti == 1) {
QStackWidget->setCurrentWidget(widget1)
CItemChild1 *chld1 = (CItemChild1 *) _itm;
widget1.load(chld1);
}
else {
QStackWidget->setCurrentWidget(widget2)
CItemChild2 *chld1 = (CItemChild2 *) _itm;
widget2.load(chld2);
}
}
Но, я прочитал в книжке по паттернам, что использовать if для выбора типа плохо.
И, как следует из паттерна Стратегия, нужно делать совсем иначе...
class CItem {
int commonVal;
virtual QWidget *getWidget(void) = 0;
};
class CItemChild1 : public CItem {
int val11;
int val12;
virtual QWidget *getWidget(void) {
return new (QWidget *) new CWidget1; // можно сделать синглтоном
}
};
class CItemChild2 : public CItem {
int val22;
int val23;
int val24;
virtual static QWidget *getWidget(void) {
return new (QWidget *) new CWidget2; // можно сделать синглтоном
}
};
void MainWidget::load(CItem *_itm)
{
if (QStackWidget->currentWidget() != NULL)
delete QStackWidget->currentWidget();
widget = _itm->getWidget();
QStackWidget->setCurrentWidget(widget)
widget.load(_itm);
}
1. Какие возможные ошибки таит этот способ?
Мне не нравится идея делать создание виджета синглтоном. Но мне и не нравится то, что указатель созданный через getWidget приходится удалять в MainWidget::load.
2. Как видите, способ сделать это через жопу я знаю. А как это сделать «красиво»?