有效的Java构建器习语等同于c++

effective java builder idiom equivalent in c++?

本文关键字:习语 等同于 c++ 构建 Java 有效      更新时间:2023-10-16

这是我在阅读Effective Java后一直在使用的一个很好的成语。我一直试图找到一个c++等同或类似的东西,并没有什么运气。在GoF书中找到的传统构建器模式并不真正适用于我的情况。它是一个复杂的对象,有一个非常混乱的构造函数。下面是Java的一个小实现。

class ComplicatedObject {
    private String field1;
    private String field2;
    private int      field3;
    private ComplicatedObject(Builder builder) {
            this.field1 = builder.myField1;
            this.field2 = builder.myField2;
            this.field3 = builder.myField3;
    }
    public static class Builder {
            private String myField1 = "some default";
            private String myField2 = "some other default";
            private int           myField3 = -1;
            public Builder() { }
            public Builder field1(String val) {
                    this.myField1 = val;
                    return this;
            }
            public Builder field2(String val) {
                    this.myField2 = val;
                    return this;
            }
            public Builder field3(int val) {
                    this.myField3 = val;
                    return this;
            }
            public ComplicatedObject build() {
                    return new ComplicatedObject(this);
            }
    }
    public static void main(final String[] args) {
    //built like this
            ComplicatedObject obj = new ComplicatedObject.Builder().field1("blah").field2("lol").field3(4).build();
    }
}

不仅可以适应c++,而且习惯用法已经从 c++中适应了

我想我第一次听到这个习语是在Java出现之前。IIRC Bjarne Stroustrup在c++第二版中提到了这一点,作为c++为什么不需要Smalltalk风格的命名参数的解释。

我可能记错了日期,但这是c++中大约15年前的。

编辑:它似乎是在 c++的设计和发展(6.5.1)中首次描述的,在那里它被称为命名函数参数
#include <iostream>
#include <string>
using namespace std;
class ComplicatedObject {
    public: class Builder {
            friend class ComplicatedObject;
            private: string myField1;
            private: string myField2;
            private: int    myField3;
            public: Builder()
                    : myField1("some default"),
                     myField2 ("some other default"),
                     myField3(-1)
            { }
            public: Builder& field1(const string& val) {
                    myField1 = val;
                    return *this;
            }
            public: Builder& field2(const string& val) {
                    myField2 = val;
                    return *this;
            }
            public: Builder& field3(int val) {
                    myField3 = val;
                    return *this;
            }
            public: ComplicatedObject build() {
                    return ComplicatedObject(*this);
            }
    };
    private: string field1;
    private: string field2;
    private: int      field3;
    private: ComplicatedObject(const Builder& builder) 
            :field1(builder.myField1),
            field2(builder.myField2),
            field3(builder.myField3)
    {}
};
int main(int argc, char** argv) {
    if (argc < 4) {
        std::cout << "not enough params.";
        return 1;
    }
    ComplicatedObject obj(ComplicatedObject::Builder().field1("blah").field2("lol").field3(4));
}

我做了最小的修改,使它成为c++,快速,安全。http://ideone.com/sCH1V