Я на самом деле никогда не использовал дизайн на основе политики на практике, и это возраст с тех пор, как я закодирован на C++, но вот моя интерпретация. Как вы указали, класс-хозяин может применять ограничения на используемые им политики, либо через интерфейсы, либо через что-то вроде using output_policy::Print;
, как показано в примере на вики.
Преимущество (или различие) метода использования заключается в том, что он менее проактивно рестриктивный и менее жесткий, поскольку политики имеют подразумеваемый контракт, который представлен непосредственно кодом, который их использует. В примере использования, учитывая текущее состояние кода, для реализации output_policy необходимо реализовать только метод Print, который возвращает что-либо и принимает все, что возвращает language_policy :: Message() (в этом случае все language_policies возвращают std :: string) , Это немного ближе к утиной печати.
Недостаток заключается в том, что подразумеваемый контракт исчезает после того, как код уходит. Другим недостатком является то, что политики имеют определенный уровень зависимости друг от друга. В качестве очень надуманного примера, если один output_policy имеет не общий метод печати, который печатает только строки, он не может использоваться с language_policy, который печатает только целые числа.
Я не понимаю, почему вы не можете добавлять интерфейсы политики, если это необходимо. Одним из примеров является то, что класс HelloWorld может захотеть ограничить output_policy, чтобы он печатал строки и ничего больше. Вы можете добиться этого, закодировав что-то вроде нижнего - обратите внимание, что вам нужно будет использовать SFINAE для обеспечения того, чтобы output_policy<std::string>
фактически реализовывал OutputPolicyInterface<std::string>
.
template<typename message_type>
class OutputPolicyInterface
{
virtual void Print(message_type message) = 0;
};
template <template<class> class output_policy, typename language_policy>
class HelloWorld : public output_policy<std::string>, public language_policy
{
public:
void Run()
{
Print(Message());
//Print(2); won't work anymore
}
};