builder模式在Java中还是随处可见的,尤其是在阅读框架源码的过程中,为什么要采用builder模式编写代码呢?因为它有诸多好处,比如
1.可读性强
这是一段比较没有追求的开发同学经常的一种写法:
Person p = new Person(); p.setName("Zhang San"); p.setSex("male"); p.setAge(25); p.setHeight("175"); p.setWeight("65"); p.setCountry("China"); p.setHomeTown("Guangzhou");
假如,他把这段代码换成Builder模式,那就变成了这样:
Person p = new Person.Builder() .name("Zhang San") .sex("male") .height(175) .weight(65) .country("China") .homeTown("Guangzhou") .build();
是不是看着非常简洁,写着也特别的享受!
2.可选择性强
可选择强是什么意思,例如类的属性(即成员变量)非常多,但是我们在实例化的时候可能根据不同场景,使用的属性数量不一样,那么假如我们使用的构造方法来实例化,那么就需要生成很多不同参数的构造方法,这不仅会为给类增加大量用处不大的代码,可读性也不强,相反,这时如果使用Builder模式,那在我们即便面对多变的需求,也不再怕了!
举个例子:
同样是Person类
public class Person { private String name; private String sex; private int height; private int weight; private int country; private int homeTown; public Person(String name, String sex) { this.name = name; this.sex = sex; } public Person(String name, String sex, int height, int weight) { this.name = name; this.sex = sex; this.height = height; this.weight = weight; } public Person(String name, int country) { this.name = name; this.country = country; } public Person(String name, int country, int homeTown) { this.name = name; this.country = country; this.homeTown = homeTown; } ... }
假如们在四种场景中实例化Person时需要的参数都不一样,那么就需要我们生成四个不同的构造函数了,如上所示。假如有更多场景就需要更多的构造函数了,当然,你也可以说使用get/set方法就可以解决这个问题了,这就回到了我们第一个优点了。我这里的意思只是想表达Builder模式能够和get/set方法一样,增加我们实例化时的可选择性,避免构造函数的冗余。
了解了Builder模式的优点了之后,那么我们就需要着手自己来写一个Builder模式了,那么,究竟怎么写一个Builder模式才是比较正确的呢?
实现
同样,以Person类作为一个例子,来学习如何实现一个Builder模式的Person类。
public class Person { private String name; private String sex; private int height; private int weight; private int country; private int homeTown; private Person(String name, String sex, int height, int weight, int country, int homeTown) { this.name = name; this.sex = sex; this.height = height; this.weight = weight; this.country = country; this.homeTown = homeTown; } // 静态内部类 static final class Builder { private String name; private String sex; private int height; private int weight; private int country; private int homeTown; public Builder name(String name) { this.name = name; return this; } public Builder setSex(String sex) { this.sex = sex; return this; } public Builder setHeight(int height) { this.height = height; return this; } public Builder setWeight(int weight) { this.weight = weight; return this; } public Builder setCountry(int country) { this.country = country; return this; } public Builder setHomeTown(int homeTown) { this.homeTown = homeTown; return this; } public Person build() { return new Person(name, sex, height, weight, country, homeTown); } } }
由上面可见,首先Builder是一个静态内部类,之所以需要静态是因为Builder类需要和外部类Person剥离关系,否则就会耦合在一起,这里的Builder相当于一个独立文件的类一样的效果;其次Person类的构造方法最好是外部类不可调用的,私有的构造器,因为我们提供了Builder的方式让外部实现了对Person类的初始化,那么我们就没必要让外部直接通过构造方法的方式创建,所以最好设置为private;再之,Builder类中的每一个方法都需要返回该构造者,因为这样,我们才能在每一次设置时都是针对同一个Builder实例进行实例;最后,在build方法才进行对Person类进行初始化,这样做的好处就是可以避免过早地对Person类初始化,当然你也是可以在Builder的构造函数里就对Person就进行初始化,这个见仁见智。
总结
Builder模式,即构造者模式,如字面意思一样,我们可以形象地把它理解为:当我们需要构建一个类时,我们需要做一系列的准备工作,在准备好之后,通过build()方法,把具有我们需要功能的类构建出来。