Builder建造者模式

最近在看设计模式之禅。该书以生动有趣的言语为我们描绘了GoF所带来的设计模式的殿堂。其中有些设计模式讲的比较好,比如抽象工厂,模板方法等。
但是在将Builder模式的时候,个人感觉和自己的理解可能有些出入,所以在此记录下自己的理解。
Builder模式的wiki地址:
wiki - Builder pattern
说个题外话,设计模式的wiki有着非常详细的内容,有兴趣的可以去学习学习,这个是设计模式的首页:
Design Pattern

对于Builder方式来讲,常用于配置对象中,比如HttpClient的Config.class等。这是由于对于这种配置对象来讲,属性项较多。而对于属性较多的对象来讲,一般还可以采用setter来进行,这样也能合理避开构造函数由于属性增多而导致的爆炸性增长。而采用Java Bean setter的这种方式的不利是由于是先new出的对象,所以在setter的过程中,可能存在中间状态,这样在多线程的状态下可能会产生问题。
由此Builder的设计模式便应运而生。Builder模式的核心是,私有化构造函数,但是提供一个静态生成Builder对象的静态方法,该对象具有和构造的对象完全相同的属性,并且具有各种setter的方法,并且采用了流式的设计,也就是setter方法返回的是自己,这样就能够将set的方法连起来,最后,当所有的属性都已经赋值完毕后,可以纸巾采用build()方法,生成对象。

我们来看一下代码,以下的代码采用了两种方式,其中第一种是我们比较熟悉的,在Effective Java中我们也有了解,而第二种则是采用Java8新特性的,也是wiki的页面中示例所提供的方法:

// Car对象
public class Car {

    // 名称
    private String name;
    // 拍照
    private String no;

    private Car(String no, String name) {
        this.name = name;
        this.no = no;
    }

    public String getName() {
        return name;
    }

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

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    // 返回Builder
    public static CarBuilder getBuilder () {
        return new CarBuilder();
    }

    // 返回Builder2
    public static CarBuilder2 getBuilder2() {
        return new CarBuilder2(Car::new);
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", no='" + no + '\'' +
                '}';
    }

    // 定义建造者,建造者的属性应该和car保持一致
    public static class CarBuilder {
        private String name;
        private String no;

        public CarBuilder() {

        }

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

        public CarBuilder setNo(String no) {
            this.no = no;
            return this;
        }

        public Car build() {
            return new Car(this.no, this.name);
        }
    }
}

// 第二种Builder方式
public class CarBuilder2 {
    private BiFunction builder;

    private String name;
    private String no;

    public CarBuilder2(BiFunction builder) {
        this.builder = builder;
    }

    public String getName() {
        return name;
    }

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

    public String getNo() {
        return no;
    }

    public CarBuilder2 setNo(String no) {
        this.no = no;
        return this;
    }

    public Car build() {
        return builder.apply(no, name);
    }
}

测试类
public class BuilderTest {

    @Test
    public void testCarBuilder() {
        Car.CarBuilder builder = Car.getBuilder();
        builder.setName("Buck").setNo("京A52450");
        Car car = builder.build();
        Assert.assertEquals(car.getName(), "Buck");
        Assert.assertEquals(car.getNo(), "京A52450");
    }

    @Test
    public void testCarBuilder2() {
        CarBuilder2 builder2 = Car.getBuilder2();
        builder2.setName("Buck").setNo("京A52450");
        Car car = builder2.build();
        Assert.assertEquals(car.getName(), "Buck");
        Assert.assertEquals(car.getNo(), "京A52450");
    }


}

你可能感兴趣的:(Builder建造者模式)