CppPatterns/Builder/main.cpp

102 lines
2.2 KiB
C++

#include <iostream>
#include <memory>
#include <numeric>
#include <vector>
std::string join(const std::vector<std::string> &values,
const std::string &separator) {
if (values.empty()) {
return "";
} else {
return std::accumulate(
std::next(values.begin()), values.end(), values.front(),
[&separator](const std::string &left, const std::string &right) {
return left + separator + right;
}
);
}
}
class Product {
public:
std::vector<std::string> parts;
void listParts() const {
std::cout << "Parts: " << join(parts, ", ") << std::endl;
}
};
class Builder {
public:
virtual ~Builder() = default;
virtual const Builder &addPartA() const = 0;
virtual const Builder &addPartB() const = 0;
virtual const Builder &addPartC() const = 0;
};
class ConcreteBuilder : public Builder {
private:
Product *product = nullptr;
public:
ConcreteBuilder() { reset(); }
~ConcreteBuilder() { delete product; }
void reset() {
if (product != nullptr) {
delete product;
}
product = new Product();
}
const Builder &addPartA() const override {
product->parts.push_back("Part A");
return *this;
}
const Builder &addPartB() const override {
product->parts.push_back("Part B");
return *this;
}
const Builder &addPartC() const override {
product->parts.push_back("Part C");
return *this;
}
Product *getProduct() {
Product *result = product;
product = nullptr;
return result;
}
};
class Director {
private:
Builder *builder = nullptr;
public:
Director(Builder *builder) : builder(builder) {}
void buildSimpleProduct() { builder->addPartA(); }
void buildFullProduct() { builder->addPartA().addPartB().addPartC(); }
};
int main(int argc, char *argv[]) {
std::cout << "Builder" << std::endl;
ConcreteBuilder builder = ConcreteBuilder();
Director director(&builder);
director.buildSimpleProduct();
auto simple_product = std::unique_ptr<Product>(builder.getProduct());
simple_product->listParts();
builder.reset();
director.buildFullProduct();
auto full_product = std::unique_ptr<Product>(builder.getProduct());
full_product->listParts();
return EXIT_SUCCESS;
}