From 80dc58f7d54d0d905ccf3db4a0d54db4eb88222b Mon Sep 17 00:00:00 2001 From: Jakub Vojvoda Date: Wed, 7 Sep 2016 09:19:54 +0200 Subject: [PATCH] add Builder pattern --- builder/Builder.cpp | 149 ++++++++++++++++++++++++++++++++++++++++++++ builder/README.md | 12 ++++ 2 files changed, 161 insertions(+) create mode 100644 builder/Builder.cpp create mode 100644 builder/README.md diff --git a/builder/Builder.cpp b/builder/Builder.cpp new file mode 100644 index 0000000..0559cac --- /dev/null +++ b/builder/Builder.cpp @@ -0,0 +1,149 @@ +/* + * C++ Design Patterns: Builder + * Author: Jakub Vojvoda [github.com/JakubVojvoda] + * 2016 + * + * Source code is licensed under MIT licence + * (for more details see LICENCE) + * + */ + +#include + +/* + * Product + * the final object that will be created using Builder + */ +class Product { +public: + void makeA(const std::string &part) { + partA = part; + } + void makeB(const std::string &part) { + partB = part; + } + void makeC(const std::string &part) { + partC = part; + } + std::string get() { + return (partA + " " + partB + " " + partC); + } + // ... + +private: + std::string partA; + std::string partB; + std::string partC; + // ... +}; + +/* + * Builder + * abstract interface for creating products + */ +class Builder { +public: + virtual ~Builder() { + // ... + } + + Product get() { + return product; + } + + virtual void buildPartA() = 0; + virtual void buildPartB() = 0; + virtual void buildPartC() = 0; + // ... + +protected: + Product product; +}; + +/* + * Concrete Builder X and Y + * create real products and stores them in the composite structure + */ +class ConcreteBuilderX : public Builder { +public: + void buildPartA() { + product.makeA("A-X"); + } + void buildPartB() { + product.makeB("B-X"); + } + void buildPartC() { + product.makeC("C-X"); + } + // ... +}; + +class ConcreteBuilderY : public Builder { +public: + void buildPartA() { + product.makeA("A-Y"); + } + void buildPartB() { + product.makeB("B-Y"); + } + void buildPartC() { + product.makeC("C-Y"); + } + // ... +}; + +/* + * Director + * responsible for managing the correct sequence of object creation + */ +class Director { +public: + Director() : builder(nullptr) {} + + ~Director() { + if (builder) { + delete builder; + } + } + + void set(Builder *b) { + if (builder) { + delete builder; + } + builder = b; + } + + Product get() { + return builder->get(); + } + + void construct() { + builder->buildPartA(); + builder->buildPartB(); + builder->buildPartC(); + // ... + } + // ... + +private: + Builder *builder; +}; + + +int main() +{ + Director director; + director.set(new ConcreteBuilderX); + director.construct(); + + Product product1 = director.get(); + std::cout << "1st product parts: " << product1.get() << std::endl; + + director.set(new ConcreteBuilderY); + director.construct(); + + Product product2 = director.get(); + std::cout << "2nd product parts: " << product2.get() << std::endl; + + return 0; +} diff --git a/builder/README.md b/builder/README.md new file mode 100644 index 0000000..f1792f0 --- /dev/null +++ b/builder/README.md @@ -0,0 +1,12 @@ +## Builder + +Builder pattern has creational purpose and separates the construction of a complex object +from its representation so that the same construction process can create different +representations. It is object pattern, ie. relationships can be changed at run-time +and are more dynamic. Often is used for building composite structures but constructing +objects requires more domain knowledge of the client than using a Factory. + +### When to use + +* the algorithm for creating a object should be independent of the parts and how they're assembled +* the construction process must allow different representations for the object that's constructed \ No newline at end of file