Java 只有一个类的生成器模式

Java 只有一个类的生成器模式,java,design-patterns,Java,Design Patterns,我正在学习构建器模式。我有一个问题,为什么不使用类ex:MyCoffe而不是2类ex:MyCoffe,BuilderClass。谢谢你的阅读 package Creational.Builder; public class MyCoffe { private String name; private int id; public MyCoffe(){ } public MyCoffe setName(Str

我正在学习构建器模式。我有一个问题,为什么不使用类ex:MyCoffe而不是2类ex:MyCoffe,BuilderClass。谢谢你的阅读

package Creational.Builder;

public class MyCoffe {

        private String name;
        private int id;

        public MyCoffe(){

        }

        public MyCoffe setName(String newName){
            this.name  = newName;
            return this;
        }

        public MyCoffe setId(int newId){
            this.id = newId;
            return this;
        }

        public MyCoffe build(){
            return this;
        }

        public String toString(){
            return name + "/" + id;
        }

        public static void main(String[] args){
            MyCoffe myCoffe = new MyCoffe().setName("HelloWorld").setId(9999);  
            System.out.println(myCoffe);

            System.out.println("Thanks for help!");
        }
}
您当然可以在某些选择的情况下进行选择,但是构建器模式的目的之一是避免类的无效实例。因此,除非MyOffe没有名称或ID是有效的,否则您不希望它的实例在没有名称或ID的情况下运行,如下所示:

MyCoffe invalid = new MyCoffe();
public class MyCoffe {

    public static class Builder {
        private MyCoffe instance;

        public Builder() {
            this.instance = new MyCoffe();
        }

        public Builder setName(String name) {
            this.instance.name = name;
            return this;
        }

        public Builder setId(int id) {
            this.instance.id = id;
            return this;
        }

        public MyCoffe build() {
            if (this.instance.name == null) {
                throw new AppropriateException("'name' is required");
            }
            if (this.instance.id == 0) { // Assumes 0 isn't a valid ID
                throw new AppropriateException("'id' is required");
            }
            return this.instance;
        }
    }

    private String name;
    private int id;

    private MyCoffe() {
    }

    public MyCoffe(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString(){
        return name + "/" + id;
    }

    public static void main(String[] args){
        MyCoffe myCoffe = new MyCoffe.Builder().setName("HelloWorld").setId(9999).build();
        System.out.println(myCoffe);

        System.out.println("Thanks for help!");
    }
}
还要注意的是,当类像这样自构建时,很容易忘记调用最终构建方法,事实上,您在main中这样做了,因此实例永远不会得到验证

因此,在构建完整、有效的实例之前,使用单独的构建器保存不完整的信息

在Java中,构建器是静态嵌套类的情况并不少见:

public class MyCoffe {

    public static class Builder {
        private String name;
        private int id;

        public Builder() {
        }

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setId(int id) {
            this.id = id;
            return this;
        }

        public MyCoffe build() {
            if (this.name == null) {
                throw new AppropriateException("'name' is required");
            }
            if (this.id == 0) { // Assumes 0 isn't a valid ID
                throw new AppropriateException("'id' is required");
            }
            return new MyCoffe(name, id);
        }
    }

    private String name;
    private int id;

    public MyCoffe(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString(){
        return name + "/" + id;
    }

    public static void main(String[] args){
        MyCoffe myCoffe = new MyCoffe.Builder().setName("HelloWorld").setId(9999).build();
        System.out.println(myCoffe);

        System.out.println("Thanks for help!");
    }
}
或者,如果像这样声明两次属性让您感到困扰,MyCoffe可以允许不完整的私有实例,如下所示:

MyCoffe invalid = new MyCoffe();
public class MyCoffe {

    public static class Builder {
        private MyCoffe instance;

        public Builder() {
            this.instance = new MyCoffe();
        }

        public Builder setName(String name) {
            this.instance.name = name;
            return this;
        }

        public Builder setId(int id) {
            this.instance.id = id;
            return this;
        }

        public MyCoffe build() {
            if (this.instance.name == null) {
                throw new AppropriateException("'name' is required");
            }
            if (this.instance.id == 0) { // Assumes 0 isn't a valid ID
                throw new AppropriateException("'id' is required");
            }
            return this.instance;
        }
    }

    private String name;
    private int id;

    private MyCoffe() {
    }

    public MyCoffe(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString(){
        return name + "/" + id;
    }

    public static void main(String[] args){
        MyCoffe myCoffe = new MyCoffe.Builder().setName("HelloWorld").setId(9999).build();
        System.out.println(myCoffe);

        System.out.println("Thanks for help!");
    }
}
您当然可以在某些选择的情况下进行选择,但是构建器模式的目的之一是避免类的无效实例。因此,除非MyOffe没有名称或ID是有效的,否则您不希望它的实例在没有名称或ID的情况下运行,如下所示:

MyCoffe invalid = new MyCoffe();
public class MyCoffe {

    public static class Builder {
        private MyCoffe instance;

        public Builder() {
            this.instance = new MyCoffe();
        }

        public Builder setName(String name) {
            this.instance.name = name;
            return this;
        }

        public Builder setId(int id) {
            this.instance.id = id;
            return this;
        }

        public MyCoffe build() {
            if (this.instance.name == null) {
                throw new AppropriateException("'name' is required");
            }
            if (this.instance.id == 0) { // Assumes 0 isn't a valid ID
                throw new AppropriateException("'id' is required");
            }
            return this.instance;
        }
    }

    private String name;
    private int id;

    private MyCoffe() {
    }

    public MyCoffe(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString(){
        return name + "/" + id;
    }

    public static void main(String[] args){
        MyCoffe myCoffe = new MyCoffe.Builder().setName("HelloWorld").setId(9999).build();
        System.out.println(myCoffe);

        System.out.println("Thanks for help!");
    }
}
还要注意的是,当类像这样自构建时,很容易忘记调用最终构建方法,事实上,您在main中这样做了,因此实例永远不会得到验证

因此,在构建完整、有效的实例之前,使用单独的构建器保存不完整的信息

在Java中,构建器是静态嵌套类的情况并不少见:

public class MyCoffe {

    public static class Builder {
        private String name;
        private int id;

        public Builder() {
        }

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setId(int id) {
            this.id = id;
            return this;
        }

        public MyCoffe build() {
            if (this.name == null) {
                throw new AppropriateException("'name' is required");
            }
            if (this.id == 0) { // Assumes 0 isn't a valid ID
                throw new AppropriateException("'id' is required");
            }
            return new MyCoffe(name, id);
        }
    }

    private String name;
    private int id;

    public MyCoffe(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString(){
        return name + "/" + id;
    }

    public static void main(String[] args){
        MyCoffe myCoffe = new MyCoffe.Builder().setName("HelloWorld").setId(9999).build();
        System.out.println(myCoffe);

        System.out.println("Thanks for help!");
    }
}
或者,如果像这样声明两次属性让您感到困扰,MyCoffe可以允许不完整的私有实例,如下所示:

MyCoffe invalid = new MyCoffe();
public class MyCoffe {

    public static class Builder {
        private MyCoffe instance;

        public Builder() {
            this.instance = new MyCoffe();
        }

        public Builder setName(String name) {
            this.instance.name = name;
            return this;
        }

        public Builder setId(int id) {
            this.instance.id = id;
            return this;
        }

        public MyCoffe build() {
            if (this.instance.name == null) {
                throw new AppropriateException("'name' is required");
            }
            if (this.instance.id == 0) { // Assumes 0 isn't a valid ID
                throw new AppropriateException("'id' is required");
            }
            return this.instance;
        }
    }

    private String name;
    private int id;

    private MyCoffe() {
    }

    public MyCoffe(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString(){
        return name + "/" + id;
    }

    public static void main(String[] args){
        MyCoffe myCoffe = new MyCoffe.Builder().setName("HelloWorld").setId(9999).build();
        System.out.println(myCoffe);

        System.out.println("Thanks for help!");
    }
}

谢谢@T.J.克劳德,我就这样开始。我正在研究你的帮助。但是如果要生成更多的生成器类,我们必须编写双属性。总是喜欢编译时错误而不是运行时异常。@MouseEvent:这适用于生成MyCoffe,而不是MyCoffe.Builder。生成器特别适用于生成最终结果所需的信息变化很大的情况,因此一个构造函数或一组具有各种排列的构造函数不是一个有效的选择。@GeoWesley:除非MyOffe也有setter,否则您只能声明两次字段。但另一种选择是让MyCoffe允许私有无效实例;我在上面添加了一个示例。我可能不会这么做,但是…@GeoWesley:这只是内部管道,你可以用上面显示的两种方式中的任何一种来编写,其中只有一种使用了新的名称id。重点是外部公共接口。谢谢@t.J.Crowder,我开始吧。我正在研究你的帮助。但是如果要生成更多的生成器类,我们必须编写双属性。总是喜欢编译时错误而不是运行时异常。@MouseEvent:这适用于生成MyCoffe,而不是MyCoffe.Builder。生成器特别适用于生成最终结果所需的信息变化很大的情况,因此一个构造函数或一组具有各种排列的构造函数不是一个有效的选择。@GeoWesley:除非MyOffe也有setter,否则您只能声明两次字段。但另一种选择是让MyCoffe允许私有无效实例;我在上面添加了一个示例。我可能不会这么做,但是…@GeoWesley:这只是内部管道,你可以用上面显示的两种方式中的任何一种来编写,其中只有一种使用了新的名称id。重点是外部公共接口。