定义
构建者模式将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。这个定义看起来文绉绉的不好理解。其实就是在创建对象时可以“按需”使用对象的的某个(某几个)属性,并在必要时对这些属性进行校验。
使用场景
构建者模式是用在创建对象的时候的,在创建对象的时候同时指定一个或多个属性值。这看起来是可以通过构造函数来实现的。比如对于对于 Student
类,可以通过以下的方式来实现:将类中的属性进行组合,然后依次写上构造函数。不过这对属性少的对象来说还可以,对属性多的对象,组合起来就很多了,而且以后增加一个属性又得进行大改动,同时还存在一个问题,就是属性的类型可能相同,导致部分组合无法实现。另外,对于属性个数多的构造函数,调用者也不太容易区分属性的个数,也不容易扩展,因此这种方式不太好。
1 | public class Student { |
使用构造函数不满足要求,此时,我们很自然的就想到了可以是用 set
方法进行属性的设置。比如
1 | public class Student { |
这种方式可以让调用者自行决定设置某些值,也解决了构造函数过多组合的问题,但是这种方式存在其他的问题:
- 不能对属性值进行校验,即:满足某种条件时允许创建对象,不满足时不允许创建
- 可能存在无效状态的问题。
先说第一个问题:不能对属性值进行校验。使用 set 的方式看起来是可以对属性值进行校验的,比如对于 setId
这个函数,我可以在函数内部判断,如果 id
范围小于 0
,则抛异常,如下所示
1 | public void setId(int id) { |
但是这是单个属性的判断,如果是多个属性联合判断就不满足了。比如要判断 id
小于 100
时,name
只能以 A
开头,这样在 Student
类内部就无法完成判断,只能让调用者进行判断,也就是说将这个控制权交给了调用方,万一调用者不进行判断,那这个限制条件就相当于无效了。
再说第二个问题,因为使用 set
的方式是先 new
一个空对象,再依次设置属性值的,那就存在一种情况,在 new
和 set
的过程中,对象是无效的(因为其他的属性值并没有设置好),此时如果获取到这个对象就可能出错。
针对以上几个问题,就产生了构建者模式的方式来创建对象。构建者模式是先将属性值设置好,然后最后按照这些值进行判断(如果需要的化),然后创建出具体的对象。
构建者模式也很简单,只需要在需要使用构建者模式的类创建一个内部类,然后对每个属性产生一个方法,最后统一暴露对外 build
方法即可。
例子
上文 Student
类的构建者代码如下
1 | public class Student { |
其他
构建者模式代码还是比较多的,如果构造函数或 set
方式能够满足要求,就没必要写太多代码用上构造者模式,或者使用 lombok
插件的 Builder
注解自动生成,不过使用 lombok
就需要项目组中所有成员都使用,不然就很乱。
参考资料
王争,《设计模式之美》