Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Почему это будет стратегия?
Вообще, навскидку не придумалась реализация стратегии без классов, буду благодарен за пример.
Dictionary<T,V>(IComparer<T>). Здесь компаратор — это как раз стратегия. А без классов — все ФП к вашим услугам, почти любая ФВП может трактоваться как стратегия.налицо (сложный) алгоритм, вариативная часть, изменена лишь реализация «замены» части алгоритма
в соответствии с реалиями си.
Теоретически, в функции needSwap могут происходить самые чудесные вещи
измерять вариативность алгоритма семантическими представлениями о сортировке не совсем корректно.
Хотя в процессе гуглежа нашлась книга «Patterns in C», реализация паттерна «Стратегия» там довольно занятная.
Это будет нарушением контракта.
Паттерн в первую очередь определяется семантикой.
Какого контракта?
Это паттерн поведения, какую семантику вы от него ожидаете?
Между базовым классом и имплементатором, или между пользователем и стратегией. Между частями паттерна, короче говоря.
Ту, которая описана в поведении, как ни странно.
Что там в этой функции — нам, как составителю алгоритма, вообще неинтересно.
Какой контракт будет нарушаться, если предикат или функция будет выполнять работу, неочевидную нам, если на выходе всё равно будет сортированная последовательность?
Это шаблонный метод, он исполняет алгоритм с вариациями, всё вполне легитимно.
Что там в этой функции — нам, как составителю алгоритма, вообще неинтересно.Дополню к ответу lair: на сортируемых элементах, как минимум, требуется наличие частичного порядка, это ключевая часть контракта алгоритма сортировки (иначе случается GIGO). Полное отсутствие побочных эффектов не является необходимым, но желательно. Как пример, отображение в множество, используемое для сравнения может кэшироваться.
Никакого отношения к шаблонам c++ он не имеет
template < typename T_Implementation >
class Crypt : public T_Implementation {
public:
DiskFileCrypt()
: T_Implementation() {};
DiskFileCrypt(const typename T_Implementation::InitParams &inParams)
: T_Implementation(inParams) {};
private:
//-------------------------------------
//Изменяемые функции
void getString(std::string &outString) {
T_Implementation::getString(outString);
}
void saveString(const std::string &inContent) {
T_Implementation::saveString(inContent);
}
virtual std::string applyEncryption(const std::string& inContent) {
return T_Implementation::applyEncryption(inContent);
}
//-------------------------------------
//Неизменяемые функции
void setupRnd() {
// Некая инициализация алгоритма случайных чисел
std::cout << "setup rnd\n";
};
void setupAlgorithm() {
// Начальные установки алгоритма шифрования
std::cout << "setup algorithm\n";
};
void wipeSpace() {
// Удаление следов работы
std::cout << "wipe\n";
};
void encrypt() {
// Установка начальных параметров
setupRnd();
setupAlgorithm();
// Получаем строку
std::string fContent; getString(fContent);
// Применяем шифрование
std::string enc = applyEncryption(fContent);
// Сохраняем строку
saveString(fContent);
// Подчищаем следы работы алгоритма
wipeSpace();
}
};
class DiskFileImplementation {
public:
typedef std::string InitParams;
DiskFileImplementation(const std::string& fName)
: fileName(fName) { };
private:
std::string fileName;
protected:
void getString(std::string &outContent) {
std::cout << "get disk file named \"" << fileName << "\"\n";
// Прочитать файл с диска и вернуть содержимое
return fileContent;
}
void saveString(const std::string &inContent) {
std::cout << "save disk file named \"" << fileName << "\"\n";
// Записать файл на диск
}
std::string applyEncryption(const std::string& content) {
// Шифрование
std::string result = someStrongEncryption(content);
return result;
}
};
typedef Crypt < DiskFileImplementation > DiskFileCrypt;Да и в таких случаях надо использовать protected, а не private.
Это раньше может и имело какой-то смысл, сейчас так или иначе DI подойдет лучше.
Например, если бы мы хотели, чтобы наследники определяли алгоритм шифрования, следовало бы сделать чисто виртуальной функцию-член класса applyEncryption.
virtual std::string applyEncryption(const std::string& content)class XorCrypt : public Crypt {
public:
XorCrypt() = default;
private:
virtual std::string getString() {
std::cout << "xor str get\n";
return "";
}
virtual void saveString(const std::string& content) {
std::cout << "xor str save\n";
}
virtual std::string applyEncryption(const std::string& content) {
// Шифрование
std::string result = applyXor(content);
std::cout << "xor\n";
return result;
}
};
Шаблонный метод