Классы на основе стратегий, как альтернатива полиморфизму
Подскажите, часто ли в практике используются классы на основе стратегий, и стоит ли рассматривать их как альтернативу для полиморфных классов в проектах? Насколько я понимаю, стратегии применимы, если нет необходимости менять поведение класса в рантайме, а только на этапе компиляции и они дают выигрыш в виде максимального повторного использования кода и расширяемости.
Пример (класс Widget, который выводит данные в разных форматах):
class person
{
public:
string name;
string number;
person(string t_name, string t_number)
: name{ move(t_name) },
number{ move(t_number) }
{}
person(person &&src) = default;
};
template<typename Tp> // Класс-стратегия, которая выводит в HTML
class outHTML
{
protected:
~outHTML() = default;
public:
void print(Tp &what)
{
cout
<< "<name>" << what.name << "</name>"
<< "<number>" << what.number << "</number>" << endl;
}
};
template<typename Tp> // Класс-стратегия, которая выводит в XML
class outXML
{
protected:
~outXML() = default;
public:
void print(Tp &what)
{
cout
<< "<Name>" << what.name << ' '
<< "<Number>" << what.number << endl;
}
};
template<typename Tp> // Класс-стратегия, которая выводит в Plain
class outPlain
{
protected:
~outPlain() = default;
public:
void print(Tp &what)
{
cout
<< "Name:" << what.name << ' '
<< "Number:" << what.number << endl;
}
};
// Класс Widget, поведение которого настраивается стратегиями
template<
template<typename> class outStrategy = outHTML, // Шаблонный шаблонный параметр. По-умолчанию вывод в HTML
typename Tp = person>
class Widget : public outStrategy<Tp> // Наследование от класса-стратегии
{
Tp content;
public:
Widget(Tp t_content) : content{ move(t_content) }
{}
void render(){ this->print(content); }
};
int main() // Точка входа
{
Widget<outPlain> w{{ "Name1", "Number1" }};
w.render();
return 0;
}
Ответы (1 шт):
@KoD, вообще вопрос не в частности - а в общем! Если есть возможность избавиться от динамического полиморфизма - это нужно сделать. Да, код будет быстрее за счет отсутствия "двойных" вызовов через vtable.
Естественно, это накладывает ограничения - "вариации" с данными определяются только этапом компиляции. А вот динамический полиморфизм определяется только наличием "обработчиков", либо в самом модуле, либо в динамических библиотеках.