将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
#include <iostream>
struct Product {
std::string name;
float price;
void show()
{
std::cout << "name:"<<name<<"; price:"<<price<<std::endl;
}
};
class Builder
{
friend class Director;
protected:
Product* product_;
Builder():product_(new Product) {}
virtual void build_name() = 0;
virtual void build_price() = 0;
public:
virtual ~Builder()
{
delete product_;
}
Product* GetResult() const
{
return product_;
}
};
class ConcreteBuilder : public Builder
{
public:
ConcreteBuilder():Builder() {}
protected:
void build_name() override
{
product_->name = "knife";
}
void build_price() override
{
product_->price=13.85f;
}
};
class Director
{
Builder* builder_;
public:
Director(Builder* const builder):builder_(builder) {}
void construct()
{
if(!builder_)return;
builder_->build_name();
builder_->build_price();
}
};
int main()
{
ConcreteBuilder builder;
Director director(&builder);
director.construct();
auto prod = builder.GetResult();
prod->show();
return 0;
}
实际工程中并没有像理论上这样使用创造者模式
实际开发中只用到了建造者模式注重零部件的组装过程
像是java有
java.lang.StringBuilder 中的建造者模式
java.lang.StringBuffer 中的建造者方法
Google Guava 中的建造者模式
mybatis 中的建造者模式
c++举一stringstream建造string的例子
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
ss << 100 << " " << 3.14f << " " << std::boolalpha << true << std::endl;
std::string s = ss.str();
std::cout << s << std::endl;
return 0;
}
一般情况下,我们更习惯使用内部类及链式调用的方式实现建造者模式,即一个产品类内部自动带有一个具体建造者,由它负责该产品的组装创建,不再需要 Builder 和 Director。这样做可以使产品表示与创建之间的联系更加紧密,结构更加紧凑,同时使得建造者模式更加简洁。
#include <iostream>
#include <sstream>
#include <memory>
class Course
{
std::string name;
float grade;
public:
using Pointer = std::shared_ptr<Course>;
public:
std::string str()
{
std::stringstream ss;
ss << "{name:[" << name << "];grade:["<<grade<<"]}";
return ss.str();
}
public:
class Builder
{
Course* course;
public:
Builder():course(new Course()) {}
virtual ~Builder()
{
delete course;
course = nullptr;
}
Builder& set_name(const std::string& name)
{
course->name = name;
return *this;
}
Builder& set_grade(const float& grade)
{
course->grade=grade;
return *this;
}
Course::Pointer build()
{
return std::make_shared<Course>(*course);
}
};
inline static Builder Builder;
};
int main()
{
auto course = Course::Builder.set_name("math").set_grade(103.0f).build();
std::cout << course->str() << std::endl;
auto course2 = Course::Builder.build();
std::cout <<course2->str() << std::endl;
return 0;
}
也可以更加c++风格一点
#include <iostream>
#include <sstream>
#include <memory>
class Course
{
std::string name;
float grade;
public:
using Pointer = std::shared_ptr<Course>;
public:
class Builder
{
Course* course;
public:
Builder():course(new Course()) {}
virtual ~Builder()
{
delete course;
course = nullptr;
}
Builder& operator << (const std::string& name)
{
course->name = name;
return *this;
}
Builder& operator << (const float& grade)
{
course->grade=grade;
return *this;
}
Course::Pointer build()
{
return std::make_shared<Course>(*course);
}
};
public:
friend std::ostream& operator<<(std::ostream& out,const Course::Pointer& course);
friend std::ostream& operator<<(std::ostream& out,const Course* const course);
friend std::ostream& operator<<(std::ostream& out,const Course& course);
};
std::ostream& operator<<(std::ostream& out,const Course& course)
{
out << "Course{name:[" << course.name << "];grade:["<<course.grade<<"]}";
return out;
}
std::ostream& operator<<(std::ostream& out,const Course* const course)
{
if (course == nullptr) return out << "nullptr";
return out << *course;
}
std::ostream& operator<<(std::ostream& out,const Course::Pointer& course)
{
return out << course.get();
}
int main()
{
Course::Builder builder;
builder << "cplusplus" << 118.5f;
auto couse1 = builder.build();
std::cout << couse1 << std::endl;
return 0;
}