Java设计模式-建造者模式

定义

Separate the construction of a complex object from its representation so that the sameconstruction process can create different representations.java

将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示。git

实现

产品类

由多个部件组成设计模式

public class Product {

    private String partA;
    private String partB;

    public String getPartA() {
        return partA;
    }

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public String getPartB() {
        return partB;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    @Override
    public String toString() {
        return "partA:" + partA + ", partB:" + partB;
    }
}
复制代码

抽象建造者

规范产品的组建,通常是由子类实现。其中,buildPart方法是零件的配置,设置一个不一样零件,或者不一样的装配顺序就可能产生不一样的产品。markdown

public abstract class Builder {

    /** * 设置产品的不一样组件/零件,以得到不一样的产品 */
    public abstract void buildPartA();

    /** * 设置产品的不一样组件/零件,以得到不一样的产品 */
    public abstract void buildPartB();

    /** * 建造产品 * @return */
    public abstract Product getProduct();

}
复制代码

具体建造者

实现抽象类定义的全部方法,而且返回一个组建好的对象ide

public class ConcreteBuilder1 extends Builder {

    private Product product = new Product();

    @Override
    public void buildPartA() {
        System.out.println("ConcreteBuilder1->buildPartA()");
        product.setPartA("组件A1");
    }

    @Override
    public void buildPartB() {
        System.out.println("ConcreteBuilder1->buildPartB()");
        product.setPartB("组件B1");
    }

    @Override
    public Product getProduct() {
        System.out.println("ConcreteBuilder1->getProduct()");
        return product;
    }
}
复制代码
public class ConcreteBuilder2 extends Builder {

    private Product product = new Product();

    @Override
    public void buildPartA() {
        System.out.println("ConcreteBuilder2->buildPartA()");
        product.setPartA("组件A2");
    }

    @Override
    public void buildPartB() {
        System.out.println("ConcreteBuilder2->buildPartB()");
        product.setPartB("组件B2");
    }

    @Override
    public Product getProduct() {
        System.out.println("ConcreteBuilder2->getProduct()");
        return product;
    }
}
复制代码

导演类

也叫指挥者类,负责安排已有模块的顺序,而后告诉Builder开始建造。导演类起到封装的做用,避免高层模块深刻到建造者内部的实现类。在建造者模式比较庞大时,导演类能够有多个。oop

public class Director {

    private Builder builder;

    public Director(Builder builder){
        this.builder = builder;
    }

    /** * 将部件partA、partB...最后组成复杂对象(使用多个简单的对象一步一步构建成一个复杂的对象) */
    public void construct(){
        builder.buildPartA();
        builder.buildPartB();
    }
}
复制代码

客户端代码

public class Client {

    public static void main(String[] args) {
        Builder builder1 = new ConcreteBuilder1();
        Director director1 = new Director(builder1);
        director1.construct();
        Product product1 = builder1.getProduct();
        System.out.println(product1);

        Builder builder2 = new ConcreteBuilder2();
        Director director2 = new Director(builder2);
        director2.construct();
        Product product2 = builder2.getProduct();
        System.out.println(product2);
    }
}
复制代码

优势

  • 封装性ui

    客户端没必要知道产品内部组成的细节this

  • 建造者独立,容易扩展spa

  • 便于控制细节风险设计

    因为具体的建造者是独立的,所以能够对建造过程逐步细化,而不对其余的模块产生任何影响

使用场景

  • 相同的方法,不一样的执行顺序,产生不一样的事件结果时,能够采用建造者模式。

  • 多个部件或零件,均可以装配到一个对象中,可是产生的运行结果又不相同时,则可使用该模式。

  • 产品类很是复杂,或者产品类中的调用顺序不一样产生了不一样的效能,这个时候使用建造者模式很是合适。

  • 在对象建立过程当中会使用到系统中的一些其余对象,这些对象在产品对象的建立过程当中不易获得时,也能够采用建造者模式封装该对象的建立过程。

    该种场景只能是一个补偿方法,由于一个对象不容易得到,而在设计阶段居然没有发觉,而要经过建立者模式柔化建立过程,自己已经违反设计的最初目标。

扩展

除上面的通用源码实现外,还有另一种更为常见的场景,就是当一个类构造器须要传入不少参数时,而且一般有一部分参数是可选的,若是使用构造方法建立这个类的实例,代码可读性会很是差,并且很容易引入错误,此时就能够利用 builder模式:

public class Person {
    private final String cardId;
    private final String name;
    private final Integer age;
    private final String sex;
    private final String address;

    public static class Builder {
        // 必须的参数
        private final String cardId;
        private final String name;
        // 可选的参数
        private Integer age;
        private String sex;
        private String address;

        public Builder(String cardId, String name) {
            this.cardId = cardId;
            this.name = name;
        }

        public Builder age(Integer age) {
            this.age = age;
            return this;
        }

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

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

        public Person build() {
            return new Person(this);
        }
    }

    private Person(Builder builder) {
        this.cardId = builder.cardId;
        this.name = builder.name;
        this.age = builder.age;
        this.sex = builder.sex;
        this.address = builder.address;
    }

    @Override
    public String toString() {
        return "cardId:" + cardId + ",name:" + name + ",age:" + age + ",sex:" + sex + ",address:" + address;
    }
}
复制代码
public class Client {

    public static void main(String[] args) {
        Person zhangsan = new Person.Builder("100000000000000000", "张三")
                .age(28)
                .sex("MALE")
                .address("BJ")
                .build();
        System.out.println(zhangsan);

        Person lisi = new Person.Builder("100000000000000001", "李四")
                .address("TJ")
                .build();
        System.out.println(lisi);
    }
}
复制代码

上面的代码经过Person的内部类Builder建立一个Person实例,其中,李四对年龄和性别进行了”保密“(age和sex均为可选参数)。能够看到,代码看起来更为优雅,大大加强了可读性,而且客户端代码也更容易编写。

源码地址:gitee.com/tianranll/j…

参考文献:《设计模式之禅》

相关文章
相关标签/搜索