只有一个类的Builder模式

时间:2016-12-28 16:00:18

标签: java design-patterns

我正在学习Builder模式。我有一个问题,为什么不使用类(例如:MyCoffe)而不是2类(例如: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!");
        }
}

1 个答案:

答案 0 :(得分:4)

在某些选择的情况下,你肯定可以,但构建器模式的目的之一是避免使用类的无效实例。因此,除非MyCoffe没有名称或ID,否则您不希望它的实例在没有名称或ID的情况下运行,如下所示:

MyCoffe invalid = new MyCoffe();

另请注意,当课程像这样自我构建时,很容易忘记调用最终build方法(事实上,您在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可以允许私有不完整的实例,如下所示:

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!");
    }
}