Ответ 1
Оба посетителя, стратегия и шаблон шаблона охватывают применение алгоритма. Самая большая разница в том, как они вызваны и как они используются на практике. Хотя может показаться, что они имеют один и тот же вариант использования, посмотрите на конструкцию объектов, чтобы увидеть разницу.
Шаблон стратегии часто используется, когда у нас нет возможности передавать функции как объект первого класса. Он ожидает очень специфический список аргументов и только этот список аргументов в своем шаблоне вызовов. Например:
struct MyStrat{
void operator()(const Foo &_input){
_input.up( 2 );
}
};
std::for_each( myFooList.begin(), myFooList.end(), MyStrat() );
который затем применяется к списку объектов типа "Foo". У нас действительно нет другого способа применить его к любому другому объекту.
Образец посетителя, с другой стороны, используется, когда мы хотим применить алгоритм к совокупности объектов, которые могут не иметь одной и той же сигнатуры или иметь одни и те же функции-члены. Мы говорим шаблон посетителя, потому что он часто используется при обходе дерева или другой коллекции "несвязанных" объектов (не связанных в смысле наследования).
struct MyVisitor{
void visit(const Foo &_input){
_input.up( 2 );
}
void visit(const Bar &_input){
_input.raiseUp( 2 );
}
void visit(const Baz &_input){
_input.setUp( 2 );
}
};
Здесь идея состоит в том, что мы хотели бы "довести" все эти объекты. Все они не используют одну и ту же подпись функции-члена, но все они концептуально связаны. Следовательно, мы можем "посещать" каждый из этих классов, но ожидать, что алгоритм будет выполнять один и тот же тип задачи.
Используя шаблон посетителя, мы избегаем необходимости обертывания каждого класса в прокси-шаблоне. Следовательно, для N классов мы хотели бы применить этот алгоритм, чтобы нам не нужно было делать N прокси-классов. Нам нужно только добавить методы N в класс посетителя.
Метод шаблона сильно отличается от шаблона посетителя и стратегии. С шаблоном то, что вы пытаетесь сделать, - это применять один и тот же тип алгоритма, но в разных подклассах внутри иерархии. Например:
class Duck{
public:
int count() =0;
void makeNoise(int times) =0;
void quack(){ makeNoise( count() ); }//the template pattern is here
};
class Mallard : public Duck{
public:
int count(){ return 4; }
void makeNoise( cout << "quack" << endl; }
};
class Daffy{
public:
int count(){ return 1; }
void makeNoise( cout << "Why I ought to..." << endl; }
};
Таким образом, результат алгоритма варьируется в пределах иерархии.