From c2dacddee5e8dca561e938ff918b7c13ffeac13c Mon Sep 17 00:00:00 2001 From: Igor Rudenko Date: Sat, 6 Aug 2022 13:11:50 +0300 Subject: [PATCH] Migrate to C++17; refactor Strategy pattern --- README.md | 4 +-- src/Strategy/Conceptual/main.cc | 64 +++++++++++++-------------------- 2 files changed, 27 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 0dfc37c..f6920c3 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ It contains C++ examples for all classic GoF design patterns. Each pattern inclu ## Requirements -The examples were written as cross platform console application using c++11. It means that you should be able to compile and execute those examples with any recent compiler. +The examples were written as cross platform console application using c++17. It means that you should be able to compile and execute those examples with any recent compiler. we recommend working with Visual Studio Code because it is a lightweight and cross-platform tool .It is a very complete IDE and is available for free (https://code.visualstudio.com/). You may need to install c++ extension and the compiler you prefer (The extension is still in preview and its focus is code editing, navigation, and debugging support for C and C++). For more information on how to use VSCode with c++ refer to: https://code.visualstudio.com/docs/languages/cpp . @@ -23,7 +23,7 @@ For code execution in VSCode you will need to set up your task first. An example { "label": "build", "type": "shell", - "command": "g++ -g -std=c++11 Conceptual/main.cc -o main", + "command": "g++ -g -std=c++17 Conceptual/main.cc -o main", "group":{ "kind": "build", "isDefault": true diff --git a/src/Strategy/Conceptual/main.cc b/src/Strategy/Conceptual/main.cc index 5d5a403..4af3b97 100644 --- a/src/Strategy/Conceptual/main.cc +++ b/src/Strategy/Conceptual/main.cc @@ -32,8 +32,8 @@ class Strategy { public: - virtual ~Strategy() {} - virtual std::string DoAlgorithm(const std::vector &data) const = 0; + virtual ~Strategy() = default; + virtual std::string doAlgorithm(std::string_view data) const = 0; }; /** @@ -54,7 +54,7 @@ class Context * всеми стратегиями через интерфейс Стратегии. */ private: - Strategy *strategy_; + std::unique_ptr strategy_; /** * * EN: Usually, the Context accepts a strategy through the constructor, but @@ -64,23 +64,18 @@ class Context * предоставляет сеттер для её изменения во время выполнения. */ public: - Context(Strategy *strategy = nullptr) : strategy_(strategy) + explicit Context(std::unique_ptr &&strategy = {}) : strategy_(std::move(strategy)) { } - ~Context() - { - delete this->strategy_; - } /** * EN: Usually, the Context allows replacing a Strategy object at runtime. * * RU: Обычно Контекст позволяет заменить объект Стратегии во время * выполнения. */ - void set_strategy(Strategy *strategy) + void set_strategy(std::unique_ptr &&strategy) { - delete this->strategy_; - this->strategy_ = strategy; + strategy_ = std::move(strategy); } /** * EN: The Context delegates some work to the Strategy object instead of @@ -89,13 +84,15 @@ class Context * RU: Вместо того, чтобы самостоятельно реализовывать множественные версии * алгоритма, Контекст делегирует некоторую работу объекту Стратегии. */ - void DoSomeBusinessLogic() const + void doSomeBusinessLogic() const { - // ... - std::cout << "Context: Sorting data using the strategy (not sure how it'll do it)\n"; - std::string result = this->strategy_->DoAlgorithm(std::vector{"a", "e", "c", "b", "d"}); - std::cout << result << "\n"; - // ... + if (strategy_) { + std::cout << "Context: Sorting data using the strategy (not sure how it'll do it)\n"; + std::string result = strategy_->doAlgorithm("aecbd"); + std::cout << result << "\n"; + } else { + std::cout << "Context: Strategy isn't set\n"; + } } }; @@ -109,12 +106,9 @@ class Context class ConcreteStrategyA : public Strategy { public: - std::string DoAlgorithm(const std::vector &data) const override + std::string doAlgorithm(std::string_view data) const override { - std::string result; - std::for_each(std::begin(data), std::end(data), [&result](const std::string &letter) { - result += letter; - }); + std::string result(data); std::sort(std::begin(result), std::end(result)); return result; @@ -122,17 +116,10 @@ class ConcreteStrategyA : public Strategy }; class ConcreteStrategyB : public Strategy { - std::string DoAlgorithm(const std::vector &data) const override + std::string doAlgorithm(std::string_view data) const override { - std::string result; - std::for_each(std::begin(data), std::end(data), [&result](const std::string &letter) { - result += letter; - }); - std::sort(std::begin(result), std::end(result)); - for (int i = 0; i < result.size() / 2; i++) - { - std::swap(result[i], result[result.size() - i - 1]); - } + std::string result(data); + std::sort(std::begin(result), std::end(result), std::greater<>()); return result; } @@ -147,20 +134,19 @@ class ConcreteStrategyB : public Strategy * выбор. */ -void ClientCode() +void clientCode() { - Context *context = new Context(new ConcreteStrategyA); + Context context(std::make_unique()); std::cout << "Client: Strategy is set to normal sorting.\n"; - context->DoSomeBusinessLogic(); + context.doSomeBusinessLogic(); std::cout << "\n"; std::cout << "Client: Strategy is set to reverse sorting.\n"; - context->set_strategy(new ConcreteStrategyB); - context->DoSomeBusinessLogic(); - delete context; + context.set_strategy(std::make_unique()); + context.doSomeBusinessLogic(); } int main() { - ClientCode(); + clientCode(); return 0; } \ No newline at end of file