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均为可选参数)。能够看到,代码看起来更为优雅,大大加强了可读性,而且客户端代码也更容易编写。
参考文献:《设计模式之禅》