namespace CommandLineArguments {
class AbstractAlgorithm
{
protected:
std::list<std::string> parameters;
public:
virtual void parameter(std::string param) {
parameters.push_back(param);
}
virtual void execute() = 0;
};
namespace {
class FlagStorage
{
private:
std::list<std::tuple<std::string, std::string, std::shared_ptr<AbstractAlgorithm>>> storage;
public:
FlagStorage() {}
void add(std::string shortflag, std::string fullflag, std::shared_ptr<AbstractAlgorithm> flagalgorithm) {
storage.push_back(std::make_tuple(shortflag, fullflag, flagalgorithm));
}
std::shared_ptr<AbstractAlgorithm> algorithm(std::string flag) const {
for (auto& element : storage)
if (std::get<0>(element) == flag or std::get<1>(element) == flag)
return std::get<2>(element);
throw std::invalid_argument("Флаг " + flag + " не используется.");
}
};
class ArgIterator
{
private:
int index;
int count;
const char** ptr;
FlagStorage storage;
public:
ArgIterator() : index(1), count(0), ptr(nullptr) {}
ArgIterator(const int count, const char** ptr, FlagStorage& algorithms) : ArgIterator() {
this->count = count;
this->ptr = ptr;
this->storage = algorithms;
}
ArgIterator(const int count, const char** ptr, const int index, FlagStorage& algorithms) : ArgIterator(count, ptr, algorithms) {
this->index = index;
}
ArgIterator& operator++()
{
if (index < count && ptr != nullptr) {
index++;
while (index < count && (ptr[index])[0] != '-')
index++;
}
return *this;
}
std::shared_ptr<AbstractAlgorithm> operator*() const {
if (index < count && ptr != nullptr) {
int inindex = index + 1;
auto answer = storage.algorithm(std::string(ptr[index]));
while (inindex < count && (ptr[inindex])[0] != '-') {
answer->parameter(ptr[inindex]);
inindex++;
}
return answer;
}
throw std::out_of_range("Выход за пределы массива.");
}
bool operator!=(const ArgIterator& obj) const {
if (index < count && ptr != nullptr)
return this->index != obj.index;
else
return false;
}
};
}
class Arguments
{
private:
int argcount;
const char** arglist;
FlagStorage storage;
public:
Arguments() : argcount(0), arglist(nullptr) {}
Arguments(int argc, const char** argv) : argcount(argc), arglist(argv) {}
ArgIterator begin() {
return ArgIterator(argcount, arglist, storage);
}
ArgIterator end() {
return ArgIterator(argcount, arglist, argcount - 1, storage);
}
FlagStorage& algorithms() {
return storage;
}
};
}
using CommandLineArguments::AbstractAlgorithm;
class SortAlgorithm : public AbstractAlgorithm
{
public:
virtual void execute() {
std::cout << "Выполнение алгоритма сортировки Параметр: ";
for (auto& prmtr : parameters)
std::cout << prmtr << " ";
std::cout << std::endl;
}
};
class InsideAlgorithm : public AbstractAlgorithm
{
public:
virtual void execute() {
std::cout << "Выполнение алгоритма загрузки данных Параметр: ";
for (auto& prmtr : parameters)
std::cout << prmtr << " ";
std::cout << std::endl;
}
};
class OutsideAlgorithm : public AbstractAlgorithm
{
public:
virtual void execute() {
std::cout << "Выполнение алгоритма выгрузки данных Параметр: ";
for (auto& prmtr : parameters)
std::cout << prmtr << " ";
std::cout << std::endl;
}
};
class ExcludeAlgorithm : public AbstractAlgorithm
{
public:
virtual void execute() {
std::cout << "Выполнение алгоритма отбора данных Параметр: ";
for (auto& prmtr : parameters)
std::cout << prmtr << " ";
std::cout << std::endl;
}
};
int main(int argc, const char* argv[]) {
setlocale(LC_ALL, "rus");
for (size_t i = 0; i < argc; i++)
std::cout << argv[i] << std::endl;
using CommandLineArguments::Arguments;
Arguments arguments(argc, argv);
arguments.algorithms().add("-s", "--sort", std::make_shared<SortAlgorithm>());
arguments.algorithms().add("-i", "--inside", std::make_shared<InsideAlgorithm>());
arguments.algorithms().add("-o", "--outside", std::make_shared<OutsideAlgorithm>());
arguments.algorithms().add("-e", "--exclude", std::make_shared<ExcludeAlgorithm>());
try {
for (auto element : arguments)
element->execute();
}
catch (const std::exception& exc) {
std::cout << exc.what();
}
}
Статья хорошо показывает применение SOLID на практике, особенно через паттерны Фабричный метод и Фасад. Однако слишком много теории для простой задачи, что может утомить новичков. Местами решение выглядит как overengineering, можно было бы упростить. Плюс за гибкость и чистый код, но переход на итераторы кажется избыточным. Хотелось бы больше кода и меньше слов. :))