写点什么

Builder 构建者模式,将复杂对象的创建过程与其表示分离,活学活用才是王道

  • 2022 年 5 月 09 日
  • 本文字数:1547 字

    阅读完需:约 5 分钟

  • 将复杂对象的创建过程(比如 set 属性值),委托给构建者去做

  • 最后通过构建者的构建方法,真正去创建对象。

  • 构建方法里调用需要实例化的类的构造函数,并将构建者的属性值复制给该对象。复制前可以做一些参数校验和默认值赋值等操作。


[](()1、通用写法

类图很简单,代码也很简单。


public class Product {


private String s1;


private String s2;


private String s3;


private Integer i1;


private Integer i2;


private Integer i3;


private Product(Builder builder) {


this.s1 = builder.s1;


this.s2 = builder.s2;


this.s3 = builder.s3;


this.i1 = builder.i1;


this.i2 = builder.i2;


this.i3 = builder.i3;


}


// 省略 getter 不提供 setter


@Override


public String toString() {


return "Product{" +


"s1='" + s1 + ''' +


", s2='" + s2 + ''' +


", s3='" + s3 + ''' +


", i1=" + i1 +


", i2=" + i2 +


", i3=" + i3 +


'}';


}


public static class Builder {


private String s1;


private String s2;


private String s3;


private Integer i1;


private Integer i2;


private Integer i3;


public static Builder create(String s1) {


return new Builder(s1);


}


private Builder(String s1) {


this.s1 = s1;


}


public Builder setS1(String s1) {


this.s1 = s1;


return this;


}


public Builder setS2(String s2) {


this.s2 = s2;


return this;


}


public Builder setS3(String s3) {


this.s3 = s3;


return this;


}


public Builder setI1(Integer i1) {


this.i1 = i1;


return this;


}


public Builder setI2(Integer i2) {


this.i2 = i2;


return this;


}


public Builder setI3(Integer i3) {


this.i3 = i3;


return this;


}


public Product build() {


// 1. s1 必 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】


if (s1 == null || s2 == "") {


throw new IllegalArgumentException("s1 必传,不可为空!");


}


// 2. s2 s3 非必填,但是具有依赖关系,即 s2 传了,s3 也必须传


if (s2 != null && s2 != "") {


if (s3 == null || s3 == "") {


throw new IllegalArgumentException("s2 与 s3 具有依赖关系!");


}


}


// 3. i1 不传或者 i1 <= 0 则默认为 1


if (i1 == null || i1 <= 0) {


i1 = 1;


}


// 4. i2 非必传 但是需要校验有效性,不能小于 0


if (i2 != null && i2 < 0) {


throw new IllegalArgumentException("i2 不能小于 0");


}


Product product = new Product(this);


return product;


}


}


}


public class Test {


public static void main(String[] args) {


Product product = Product.Builder.create("1")


.setS2("2")


.setS3("3")


.setI1(0)


.setI2(2)


.setI3(3)


.build();


System.out.println(product.toString());


}


}


// Product{s1='1', s2='2', s3='3', i1=1, i2=2, i3=3}


注意:


  • Builder可以是内部类,也可以是外部类,视情况而定,一般情况是作为产品类的内部类,这样产品类多了,不至于多出很多Builder类,让代码结构变得复杂。

  • Builder和产品类中代码重复,产品类的属性需要复制一份到Builder,并且要保持同步更新。

  • Builderset方法需要返回Builder本身,达到链式调用的效果。

  • Builderbuild()方法中实例化产品类,并且做一些必要的参数校验,非必填的参数校验也可以放到set里。

  • Product产品类的构造函数设置成private的,并且没有对外提供set方法,主要是为了创建产品类只能通过Builder,并且创建出来的对象是不可修改的。

  • Product的构造函数的参数为Builder,这样为了方便将值复制给Product,也可以不用这样做。

  • Product.Builder对外提供了一个静态方法create,这个方法可有可无,是将Builder的创建隔离,同时一些必填参数也可以通过Builder的构造函数传入。

[](()2、构建者模式的优缺点

(1)优点:隔离了复杂对象的创建细节,方便客户端调用,减少了不必要的 bug。

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
Builder构建者模式,将复杂对象的创建过程与其表示分离,活学活用才是王道_Java_爱好编程进阶_InfoQ写作社区