重构:遇到多个参数初始化时可考虑建造者模式

前面我们提到使用静态工厂方法代替构造方法,因为静态工厂相对于构造方法有诸多个优势。但静态工厂和构造方法有一个共同的局限性:它们都不能很好地扩展到大量的可选参数。比如我们有一个用于描述字段属性的类,一个字段通常包含:字段名、字段标题、字段是否可见、字段是否必填等等属性,其中字段名、字段标题是必填的,其它都是非必填。

对于这样的类,我们应该怎么设计它。通常来说,大部分的开发者都会想到使用重载的方式来提供几个可能的构造方法保证客户端可以快速的创建出这样的一个字段对象出来。比如这样:

public class Field {
  private String name;
  private String title;
  private boolean visible = true;
  private boolean allowBlank = true;

  public Field(String name, String title) {
    this(name, title, true);
  }

  public Field(String name, String title, boolean visible) {
    this(name, title, visible, true);
  }

  public Field(String name, String title, boolean visible, boolean allowBlank) {
    this.name = name;
    this.title = title;
    this.visible = visible;
    this.allowBlank = allowBlank;
  }
}

当我们想要创建一个可见且非必填的字段时,就可以调用最短的构造方法创建对象;当我们想要创建一个不可见且必填的字段时,那我们就得调用最长的构造方法。

我这里只是简单的举了个只包含四个属性的例子,这么看来这种方式还不算很糟糕。但问题是随着属性的增加,它很快就失去了控制。最后我们创建一个对象就不得不这样:

Field field = new Field("text", "单行文本");
field.setVisible(false);
field.setAllowBlank(false);
field.setDefaultValue(xxx);
field.setReadOnly(false);
...

类似上述的写法,我们称之为JavaBeans模式。这种模式下先创建一个最简单的对象,然后通过调用setter方法来设置每个参数。这种方式虽然创建对象很容易,写出来的代码阅读起来也很容易。但是它最大的缺点是:该模式使得把类做成不可变类的可能性不复存在。

说了这么多,我们现在就正式进入本篇的主题——建造者模式。建造者模式可以保证像重载的构造方法那样安全,也能像JavaBeans模式那样可读。通常来说,建造者模式不直接生成最终对象,而是让客户端得到一个builder对象,然后在builder对象上调用类似于setter的方法来设置每个相关的可选参数。最后调用无参的build方法来生成通常不可变的对象。如下:

public class Field {
  private String name;
  private String title;
  private boolean visible = true;
  private boolean allowBlank = true;

  private Field(Builder builder) {
    this.name = builder.name;
    this.title = builder.title;
    this.visible = builder.visible;
    this.allowBlank = builder.allowBlank;
  }

  public static class Builder {
    private String name;
    private String title;
    private boolean visible = true;
    private boolean allowBlank = true;

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

    public Builder visible(boolean visible) {
      this.visible = visible;
      return this;
    }

    public Builder allowBlank(boolean allowBlank) {
      this.allowBlank = allowBlank;
      return this;
    }

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

builder的设值方法返回builder本身,以便把调用链接起来,得到一个流式的API。客户端代码:

Field field = new Builder("text", "单行文本").visible(false).allowBlank(false).build();

总结,如果类的构造方法或者静态工厂中具有多个参数,设计这种类时,Builder模式就是一种不错的选择,特别适当大多数参数都是可选或者类型相同的时候。

——End——
更多精彩分享,可扫码关注微信公众号哦。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值