LINUX.ORG.RU

Паттерн стратегия ужасен?

 , , ,


0

2

Привет. Паттерн стратегия ужасен!

Есть абстрактный класс 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. Как видите, способ сделать это через жопу я знаю. А как это сделать «красиво»?


Но, я прочитал в книжке по паттернам, что использовать if для выбора типа плохо.

Программировать не научился, а книжки по паттернам читает. И применяет от фонаря.

Pavval ★★★★★ ()

Ну создавать в CItem QWidget точно не стоит. В принципе, первый вариант не плохой. Может получится красивее если вместо my_rtti применить visitor ну или dynamic_cast, на краняк.

four_str_sam ()

Паттерн «есть паттерн для этого» ужасен.

идиомы не паттерны, не трафареты, образцы.

qulinxao ★★☆ ()

Что за херню я прочитал. Чувак, тебе явно рано читать о паттернах. Погоди чуток, попиши код, когда в голове будут складываться абстракции, читай о паттернах. Гарантирую, что половина того, что прочитаешь, для тебя будет очевидным. Как бы то ни было, дочитай до порождающих паттернов. Не вдаюсь в кашу, которую ты написал, но, похоже, что тебе нужен паттерн абстрактная фабрика.

anonymous ()
Ответ на: комментарий от Pavval

Блин. Делать-то что? Как это написать через жопу, я знаю. Как это написать красиво? Есть идеи?

JANB ()

Я чёт не понял... с каких пор это у нас virtual методы могут быть static?

Adonai ★★★ ()
Ответ на: комментарий от Adonai

Глупость написал. Уже исправил)

Как бы ты решил такую задачу?

JANB ()
Ответ на: комментарий от JANB

Да почти так, как ты и написал. Два наследника, у каждого своя реализация метода, и паттерны никакие не нужны, обычный приём полиморфизма.

Паттерн визитор применяется в случае, если нельзя изменять исходные коды того, над чем работаешь, в эту сторону не кури.

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

Adonai ★★★ ()
Последнее исправление: Adonai (всего исправлений: 2)

Сделай, чтоб я этого не видел!

Никогда не суй представление в классы данных, это мегаархиантипаттерн - источник ошибок, нарушения слоистости, добавление циклической связаности, невозможность использовать альтернативное отображение и невозможность разнесения компонент с целью масштабирования!

anonymous ()

И причём тут стратегия, причём тут одиночка?

Что за бред ты читаешь, или ты читаешь только забойные фразы вроде «использовать if для выбора типа плохо»

anonymous ()

Паттерн ужаса стратежен!

^^ fixed ^^

MKuznetsov ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.