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

173 lines
4.6 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:
void setCrew(int crew) { _crew = crew; }
void setArmor(int armor) { _armor = armor; }
void setCannons(int cannons) { _canons = cannons; }
void setDurability(int durability) { _durability = durability; }
const std::string& name() const { return _name; }
int capacity() const { return _capacity; }
int crew() const { return _crew; }
int armor() const { return _armor; }
int canons() const { return _canons; }
int durability() const { return _durability; }
private:
// Allow to be created only by std::unique_ptr
friend std::unique_ptr<Ship> std::make_unique<Ship>();
friend class ShipBuilder;
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->_time = time;
return *this;
}
ShipBuilder& setStrategy(std::unique_ptr<DifficultStrategy<Ship, bool>> strategy) {
_ship->_strategy = std::move(strategy);
return *this;
}
ShipBuilder& setName(const std::string& name) {
_ship->_name = name;
return *this;
}
ShipBuilder& setCapacity(int capacity) {
_ship->_capacity = capacity;
return *this;
}
ShipBuilder& setMaxCrew(int maxCrew) {
_ship->_maxCrew = maxCrew;
return *this;
}
ShipBuilder& setCrew(int crew) {
_ship->_crew = crew;
return *this;
}
ShipBuilder& setVisitor(std::unique_ptr<PrintVisitor> visitor) {
_ship->_visitor = std::move(visitor);
return *this;
}
ShipBuilder& setArmor(int armor) {
_ship->_armor = armor;
return *this;
}
ShipBuilder& setMaxArmor(int maxArmor) {
_ship->_maxArmor = maxArmor;
return *this;
}
ShipBuilder& setCannons(int cannons) {
_ship->_canons = cannons;
return *this;
}
ShipBuilder& setMaxCannons(int maxCannons) {
_ship->_maxCannons = maxCannons;
return *this;
}
ShipBuilder& setDurability(int durability) {
_ship->_durability = durability;
return *this;
}
ShipBuilder& setMaxDurability(int maxDurability) {
_ship->_maxDurability = maxDurability;
return *this;
}
private:
std::unique_ptr<Ship> _ship;
};
class ShipJsonBuilder : private ShipBuilder {
public:
std::unique_ptr<Ship> buildBrig(Time* time, const std::string& name) {
return setTime(time)
.setName(name)
.setCapacity(500)
.setMaxCrew(200)
.setMaxArmor(1000)
.setMaxCannons(20)
.setMaxDurability(1000)
.build();
}
std::unique_ptr<Ship> buildFrigate();
std::unique_ptr<Ship> buildGaleon();
};
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';
}
auto ship3 = ShipJsonBuilder().buildBrig(&time, "Black Widow");
if (ship3) {
std::cout << "Ship name: " << ship3->name() << '\n';
}
}