trainings/CreatingReliableSoftwareCpp/Presentation/examples/builder/builder.cpp

204 lines
5.3 KiB
C++

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
#include <set>
#include <vector>
struct Time {};
template <typename T, typename U>
struct DifficultStrategy {};
struct PrintVisitor {};
class Ship {
public:
Ship& setTime(Time* time) {
_time = time;
return *this;
}
Ship& setStrategy(std::unique_ptr<DifficultStrategy<Ship, bool>> strategy) {
_strategy = std::move(strategy);
return *this;
}
Ship& setName(const std::string& name) {
_name = name;
return *this;
}
Ship& setCapacity(int capacity) {
_capacity = capacity;
return *this;
}
Ship& setMaxCrew(int maxCrew) {
_maxCrew = maxCrew;
return *this;
}
Ship& setCrew(int crew) {
_crew = crew;
return *this;
}
Ship& setVisitor(std::unique_ptr<PrintVisitor> visitor) {
visitor = std::move(_visitor);
return *this;
}
Ship& setArmor(int armor) {
_armor = armor;
return *this;
}
Ship& setMaxArmor(int maxArmor) {
_maxArmor = maxArmor;
return *this;
}
Ship& setCannons(int cannons) {
_canons = cannons;
return *this;
}
Ship& setMaxCannons(int maxCannons) {
_maxCannons = maxCannons;
return *this;
}
Ship& setDurability(int durability) {
_durability = durability;
return *this;
}
Ship& setMaxDurability(int maxDurability) {
_maxDurability = maxDurability;
return *this;
}
const Time* time() const { return _time; }
const std::string& name() const { return _name; }
int capacity() const { return _capacity; }
int maxCrew() const { return _maxCrew; }
int crew() const { return _crew; }
int armor() const { return _armor; }
int maxArmor() const { return _maxArmor; }
int canons() const { return _canons; }
int maxCannons() const { return _maxCannons; }
int durability() const { return _durability; }
int maxDurability() const { return _maxDurability; }
private:
// Allow to be created only by std::unique_ptr
friend std::unique_ptr<Ship> std::make_unique<Ship>();
Ship() = default;
Time* _time{};
std::unique_ptr<DifficultStrategy<Ship, bool>> _strategy{};
std::string _name{};
int _capacity{-1};
int _maxCrew{-1};
int _crew{10};
std::unique_ptr<PrintVisitor> _visitor{};
int _armor{0};
int _maxArmor{-1};
int _canons{0};
int _maxCannons{-1};
int _durability{100};
int _maxDurability{-1};
};
class ShipBuilder {
public:
ShipBuilder()
: _ship(std::make_unique<Ship>()) {}
[[nodiscard]] std::unique_ptr<Ship> build() {
if (!_ship) {
std::cout << "Builder may be use once\n";
return nullptr;
}
// Check mandatory fields
if (!_ship->time() ||
_ship->name().empty() ||
_ship->capacity() == -1 ||
_ship->maxCrew() == -1 ||
_ship->maxArmor() == -1 ||
_ship->maxCannons() == -1 ||
_ship->maxDurability() == -1) {
std::cout << "Mandatory fields are not set!\n";
return nullptr;
}
return std::move(_ship);
}
ShipBuilder& setTime(Time* time) {
_ship->setTime(time);
return *this;
}
ShipBuilder& setStrategy(std::unique_ptr<DifficultStrategy<Ship, bool>> strategy) {
_ship->setStrategy(std::move(strategy));
return *this;
}
ShipBuilder& setName(const std::string& name) {
_ship->setName(name);
return *this;
}
ShipBuilder& setCapacity(int capacity) {
_ship->setCapacity(capacity);
return *this;
}
ShipBuilder& setMaxCrew(int maxCrew) {
_ship->setMaxCrew(maxCrew);
return *this;
}
ShipBuilder& setCrew(int crew) {
_ship->setCrew(crew);
return *this;
}
ShipBuilder& setVisitor(std::unique_ptr<PrintVisitor> visitor) {
_ship->setVisitor(std::move(visitor));
return *this;
}
ShipBuilder& setArmor(int armor) {
_ship->setArmor(armor);
return *this;
}
ShipBuilder& setMaxArmor(int maxArmor) {
_ship->setMaxArmor(maxArmor);
return *this;
}
ShipBuilder& setCannons(int cannons) {
_ship->setCannons(cannons);
return *this;
}
ShipBuilder& setMaxCannons(int maxCannons) {
_ship->setMaxCannons(maxCannons);
return *this;
}
ShipBuilder& setDurability(int durability) {
_ship->setDurability(durability);
return *this;
}
ShipBuilder& setMaxDurability(int maxDurability) {
_ship->setMaxDurability(maxDurability);
return *this;
}
private:
std::unique_ptr<Ship> _ship;
};
int main() {
auto ship = ShipBuilder().build();
if (ship) {
std::cout << "Ship name: " << ship->name() << '\n';
}
Time time;
auto ship2 = ShipBuilder()
.setTime(&time)
.setName("Black Pearl")
.setCapacity(500)
.setMaxCrew(200)
.setMaxArmor(1000)
.setMaxCannons(20)
.setMaxDurability(1000)
.build();
if (ship2) {
std::cout << "Ship name: " << ship2->name() << '\n';
}
}