Как избежать дубликации кода?
Я новичек, пытаюсь реализовать паттерн стратегия для генерации пароля.
Пароль может быть simple , medium и strong.
Из параметров командной строки узнаю какой пароль нужен пользователю и исходя из этого выбирают стратегию.
Столкнулся с такой проблемой что, в функции use_main_strategy() сильная дубликация кода.
Как можно избежать этого?
main.cpp
#include "errors.h"
#include "argparser.h"
#include "alphabet.h"
#include "passwordgenerator.h"
#include "strategy.h"
#include <iostream>
#include <stdexcept>
#include <map>
#include <string>
#include <fstream>
#include <QDebug>
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QScopedPointer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QFile>
using namespace std;
//использование выбранной стратегии
string use_main_straregy(string _strat, int _lenght_pass, string _alphabet) {
PasswordGenerator _pwdgen;
if (_strat == "simple"){
Simple _strateg;
_pwdgen.setStrategy(&_strateg);
return _pwdgen.useStrategy(_lenght_pass, _alphabet);
}
if (_strat == "medium"){
Medium _strateg;
_pwdgen.setStrategy(&_strateg);
return _pwdgen.useStrategy(_lenght_pass, _alphabet);
}
if (_strat == "strong"){
Strong _strateg;
_pwdgen.setStrategy(&_strateg);
return _pwdgen.useStrategy(_lenght_pass, _alphabet);
}
}
int main(int argc, char** argv) {
try {
auto parser = parse_args(QCoreApplication(argc, argv));
auto strat = select_alphabet(*parser);//выбор стратегии алфавита (слабый,средний или сильный)
auto length = parser->value("length").toUInt();//длина алфавита
cout << use_main_straregy(strat,length,alphabet) << endl;
}
catch (const exception& ex) {
cout << "ERROR: " << ex.what() << endl;
}
return 0;
}
strategy.h
#pragma once
#include <iostream>
using namespace std;
class Strategy {
public:
virtual ~Strategy() {}
virtual string use(int lenght,string alpahbet) = 0;
};
class Simple: public Strategy {
public:
string alphabet = "abcdefghijklmopqrtsuvwxyzABCDEFGHIJKLMOPQRTSUVWXYZ0123456789";
string use(int lenght,string alpahbet);
};
class Medium: public Strategy {
public:
string alphabet = "abcdefghijklmopqrtsuvwxyzABCDEFGHIJKLMOPQRTSUVWXYZ0123456789!@#_";
string use(int lenght,string alpahbet);
};
class Strong: public Strategy {
public:
string alphabet = "abcdefghijklmopqrtsuvwxyzABCDEFGHIJKLMOPQRTSUVWXYZ0123456789!@#$%^&*()-_+=";
string use(int lenght,string alpahbet);
};
Ответы (2 шт):
У вас нет "сильной" дубликации кода, на самом деле у вас дублируются только две строки, но это меньшая проблема нежели повторные проверки или возврат мусора в вашей фукции. Учитывая, что ваши стратегии наследуются от базового класса, предлагаю сделать подобным образом
Strateg *_strateg = nullptr;
if (_strat == "simple"){
_strateg = new Simple;
} else
if (_strat == "medium"){
_strated = new Medium;
} else
if (_strat == "strong"){
_strated = new Strong;
}
if (_strategy) {
PasswordGenerator _pwdgen;
_pwdgen.setStrategy(&_strateg);
std::string retval = _pwdgen.useStrategy(_lenght_pass, _alphabet);
delete _strateg;
return retval;
}
return "";
PS и лучше не применяйте имена переменных начиная с подчеркивания: хоть зарезервированными считаются только имена с двумя подчеркиваниями, но разработчики stl могут применять и имена с одним подчеркиванием - такое бывает
Я бы вынес дублирующийся код в лямбду, примерно так:
PasswordGenerator _pwdgen;
auto lambda = [&](auto &&_strateg)
{
_pwdgen.setStrategy(&_strateg);
return _pwdgen.useStrategy(_lenght_pass, _alphabet);
};
if (_strat == "simple")
return lambda(Simple{});
if (_strat == "medium")
return lambda(Medium{});