GoF设计模式-Builder(创造者)

韩良策
2023-12-01

简介

定义

将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

类图

Director Builder builder Director(Builder builder) construct() : void Product partA PartA partB PartB setPartA(a :PartA) : void setPartB(b :PartB) : void «abstract» Builder Product product buildPartA() : void buildPartB() : void getResult() : Product ConcreteBuilderA ConcreteBuilderB

例子

理论上的一个例子

#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;
}

c++ stringstream

实际工程中并没有像理论上这样使用创造者模式
实际开发中只用到了建造者模式注重零部件的组装过程
像是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

一般情况下,我们更习惯使用内部类及链式调用的方式实现建造者模式,即一个产品类内部自动带有一个具体建造者,由它负责该产品的组装创建,不再需要 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;
}

 类似资料: