C++ Design Pattern Creational builder 01
Date: 2021-09-12Last modified: 2023-03-22
Table of contents
// ----------------------------------------------------------------------
// Person.h
// ----------------------------------------------------------------------
class PersonBuilder;
class Person {
// address
std::string street_address, post_code, city;
// employment
std::string company_name, position;
int annual_income = 0;
Person() { TRACE; }
public:
~Person() { TRACE; }
static PersonBuilder create();
// clang-format off
Person( Person &&other ) :
street_address { std::move( other.street_address ) },
post_code { std::move( other.post_code ) },
city { std::move( other.city ) },
company_name { std::move( other.company_name ) },
position { std::move( other.position ) },
annual_income { other.annual_income }
{
TRACE;
}
// clang-format on
Person &operator=(Person &&other) {
TRACE;
if (this == &other) return *this;
street_address = std::move(other.street_address);
post_code = std::move(other.post_code);
city = std::move(other.city);
company_name = std::move(other.company_name);
position = std::move(other.position);
annual_income = other.annual_income;
return *this;
}
friend std::ostream &operator<<(std::ostream &os, const Person &obj) {
TRACE;
// clang-format off
return os
<< "street_address: " << obj.street_address
<< " post_code: " << obj.post_code
<< " city: " << obj.city
<< " company_name: " << obj.company_name
<< " position: " << obj.position
<< " annual_income: " << obj.annual_income;
// clang-format on
}
friend class PersonBuilder;
friend class PersonAddressBuilder;
friend class PersonJobBuilder;
};
// ----------------------------------------------------------------------
// PersonBuilder.h
// ----------------------------------------------------------------------
class PersonAddressBuilder;
class PersonJobBuilder;
class PersonBuilderBase {
protected:
Person &person;
explicit PersonBuilderBase(Person &person) : person{person} { TRACE; }
public:
operator Person() const {
TRACE;
return std::move(person);
}
// builder facets
PersonAddressBuilder lives() const;
PersonJobBuilder works() const;
};
class PersonBuilder : public PersonBuilderBase {
Person p;
public:
PersonBuilder() : PersonBuilderBase{p} { TRACE; }
};
// ----------------------------------------------------------------------
// Person.cpp
// ----------------------------------------------------------------------
PersonBuilder Person::create() {
TRACE;
return PersonBuilder{};
}
// ----------------------------------------------------------------------
// PersonAddressBuilder.h
// ----------------------------------------------------------------------
class PersonAddressBuilder : public PersonBuilderBase {
typedef PersonAddressBuilder Self;
public:
explicit PersonAddressBuilder(Person &person) : PersonBuilderBase{person} {
TRACE;
}
Self &at(const std::string &street_address) {
TRACE;
person.street_address = street_address;
return *this;
}
Self &with_postcode(const std::string &post_code) {
TRACE;
person.post_code = post_code;
return *this;
}
Self &in(const std::string &city) {
TRACE;
person.city = city;
return *this;
}
};
// ----------------------------------------------------------------------
// PersonJobBuilder.h
// ----------------------------------------------------------------------
class PersonJobBuilder : public PersonBuilderBase {
typedef PersonJobBuilder Self;
public:
explicit PersonJobBuilder(Person &person) : PersonBuilderBase{person} {
TRACE;
}
Self &at(const std::string &company_name) {
TRACE;
person.company_name = company_name;
return *this;
}
Self &as_a(const std::string &position) {
TRACE;
person.position = position;
return *this;
}
Self &earning(int annual_income) {
TRACE;
person.annual_income = annual_income;
return *this;
}
};
// ----------------------------------------------------------------------
// PersonBuilder.cpp
// ----------------------------------------------------------------------
PersonAddressBuilder PersonBuilderBase::lives() const {
TRACE;
return PersonAddressBuilder{person};
}
PersonJobBuilder PersonBuilderBase::works() const {
TRACE;
return PersonJobBuilder{person};
}
Person p = Person::create()
.lives()
.at("123 London Road")
.with_postcode("SW1 1GB")
.in("London")
.works()
.at("PragmaSoft")
.as_a("Consultant")
.earning(10e6);
std::cout << "--------------" << std::endl;
std::cout << p << std::endl;
Possible output
static PersonBuilder Person::create()
PersonBuilderBase::PersonBuilderBase(Person &)
Person::Person()
PersonBuilder::PersonBuilder()
PersonAddressBuilder PersonBuilderBase::lives() const
PersonBuilderBase::PersonBuilderBase(Person &)
PersonAddressBuilder::PersonAddressBuilder(Person &)
Self &PersonAddressBuilder::at(const std::string &)
Self &PersonAddressBuilder::with_postcode(const std::string &)
Self &PersonAddressBuilder::in(const std::string &)
PersonJobBuilder PersonBuilderBase::works() const
PersonBuilderBase::PersonBuilderBase(Person &)
PersonJobBuilder::PersonJobBuilder(Person &)
Self &PersonJobBuilder::at(const std::string &)
Self &PersonJobBuilder::as_a(const std::string &)
Self &PersonJobBuilder::earning(int)
Person PersonBuilderBase::operator Person() const
Person::Person(Person &&)
Person::~Person()
--------------
std::ostream &operator<<(std::ostream &, const Person &)
street_address: 123 London Road post_code: SW1 1GB city: London company_name: PragmaSoft position: Consultant annual_income: 10000000
Person::~Person()