2012-03-10 2 views
1

При реализации политик необходимо следовать определенному интерфейсу. Насколько я понимаю, политика должна быть способна заменить друг друга. В современной C++ книге политики Ch 1.5 3 имеют один и тот же интерфейс «T * Create() {}». Почему нет необходимости его абстрагировать. Было бы важно, есть ли количество интерфейсов, которые должны иметь политики. из я понимаю, абстрактный класс дает рецепт, для которого интерфейсы должны быть в конкретных классах (классы политики). В «Wikipedia example« использование »определяет, какие интерфейсы должна иметь политика, но не через абстрактный класс. Не следует ли абстрактному классу убедиться, что производные классы имеют необходимые интерфейсы?Почему не абстрактные политики?

Что мне не хватает?

ответ

2

Существует разница в том, что интерфейс с использованием абстрактного базового класса имеет виртуальные функции, обеспечивающие полиморфизм во время выполнения.

Политики используются для предоставления полиморфизма времени компиляции для шаблонов. Компилятор заметит, имеет ли ваш класс политики T* Create() или нет. Если это не так, вы получите ошибку времени компиляции при попытке ее использования.

1

Я на самом деле никогда не использовал дизайн на основе политики на практике, и это возраст с тех пор, как я закодирован на 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 
    } 
}; 
Смежные вопросы