最近又看到了Builder构建器模式,想起了之前看的effective java中的讲的创建和销毁对象的方法里面的一章讲到了这个模式,当时不大理解。在网上搜到了好多的博文发现也没有讲清楚真正的设计思想。又看了一遍想了一下,记录下来。

主要不理解的地方就是我印象中的三种对象构建模式之间的区别:构造方法,javaBean模式的get、set方法,Builder模式。

1.构造方法模式

Public class User{
 private String name;
 private byte sex;
 private int age;
 private long phone;

 public User(String name,byte sex,int age,long phone){
  this.name = name;
  this.sex = sex;
  this.age = age;
  this.phone = phone;
 }
}

这种是最常用的模式,大家都熟悉。

2.javaBean的get,set方法

Public class User{
    private String name;
    private byte sex;
    private int age;
    private long phone;

    public String getName() {
        return name;
    }

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

    public byte getSex() {
        return sex;
    }

    public void setSex(byte sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public long getPhone() {
        return phone;
    }

    public void setPhone(long phone) {
        this.phone = phone;
    }
}

3.Builder构建器模式

public class Contact {
    private String name;
    private byte sex;
    private int age;
    private long phone;

    public String getName() {
        return name;
    }

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

    public byte getSex() {
        return sex;
    }

    public void setSex(byte sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public long getPhone() {
        return phone;
    }

    public void setPhone(long phone) {
        this.phone = phone;
    }

    public static class Builder {
        private String name;
        private byte sex;
        private int age;
        private long phone;
        // 构建的步骤
        public Builder(String name) {
            this.name = name;
        }
        public Builder age(int val) {
            age = val;
            return this;
        }
        public Builder sex(byte val) {
            sex = val;
            return this;
        }
        public Builder phone(long val) {
            phone = val;
            return this;
        }
        public Contact build() { // 构建,返回一个新对象
            return new Contact(this);
        }
    }
    private Contact(Builder b) {
        age = b.age;
        sex = b.sex;
        name = b.name;
        phone = b.phone;
    }
}

比较:

之前一直不理解Builder构建器为什么要创建内部类来实现。更多的人说可以使创建对象时代码更优美,我觉得把javaBean模式的set方法的返回值修改成当前类本身不是也可以实现么。类似

public class Contact {
    private String name;
    private byte sex;
    private int age;
    private long phone;

    public String getName() {
        return name;
    }

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

    public byte getSex() {
        return sex;
    }

    public Contact setSex(byte sex) {
        this.sex = sex;
        return this;
    }

    public int getAge() {
        return age;
    }

    public Contact setAge(int age) {
        this.age = age;
        return this;
    }

    public long getPhone() {
        return phone;
    }

    public Contact setPhone(long phone) {
        this.phone = phone;
        return this;
    }
}

这样在构建的时候也可以直接写new Contact().setAge(0).setName("wer").setPhone(213423423423L).setSex((byte) 1);

所以说Builder构建器的真正意义并不是代码优美。

Effective Java中写到:遗憾的是,javaBeans模式自身有着很严重的缺点。因为构造过程被分到了几个调用中,在构建过程中JavaBeans可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。试图使用处于不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此它调试起来十分困难。与此相关的另一点不足在于,JavaBeans模式阻止了把类做成不可变得可能,这就需要程序员付出额外的努力来确保它的线程安全。

理解了这段意思之后就可以明白,三种创建对象的方式的区别:

构造方法:可以保证对象不被修改,但是构建不够灵活,对于传不同参数个数时需要多个构造函数。

JavaBeans:构建之后能够灵活的改变对象属性(既是优势也是劣势,需要根据需要来使用),但是赋值过程不是一次性的,也就不是线程安全的。

Builder构建器:既能保证构建时的灵活性,还能保证创建对象的一次性。这就需要一个内部类来存储预设置的属性,在调用bulid()方法的时候一次性构建出来所需要的对象。

03-13 20:15