一个类中如果属性太多,则写构造方法时很容易产生臃肿的现象。
一般写法有两种,一种是采用重叠构造区模式,先写第一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个构造器有两个可选参数,以此类推;
如果参数比较多时,类里面会出现一堆构造方法,并且阅读困难,很容易就把两个属性参数写颠倒位置了,编译不会出错,但运行就会出错了
第二种是采用 javabean的写法,不重写构造方法,采用默认的构造方法,写一堆属性的setter方法,通过生成对象,让后调用setter方法给属性赋值。 这种方法有个劣势就是构造的过程被分到几个调用中,在构造中可能处于不一致状态,无法保证一致性。
还有一种替代方法,就是builder模式
在实体类Nutrition 里面重新写一个内部静态类Builer,使Builer类的属性和 类 Nutrition 的属性保持一致,例如
public class Nutrition {
private int age;
private int height;
private String name;
public static class Builer{
private int age;
private int height;
private String name;
public Builer setAge(int age) {
this.age = age;
return this;
}
public Builer setHeight(int height) {
this.height = height;
return this;
}
public Builer setName(String name) {
this.name = name;
return this;
}
public Nutrition builder(){
return new Nutrition(this);
}
}
private Nutrition(Builer builder) {
age = builder.age;
height = builder.height;
name = builder.name;
}
}
创建时 Nutrition nur = new Nutrition.Builer().setAge(12).setHeight(175).setName("Tom").builder(); 即可。
这种好处是编译时即可检查参数的正确性,Builer模式可以选择参数,可多可少,十分灵活,并且赋值后,调用builder()方法创建对象。
做Android开发的小伙伴,做图片下载的时候,会用到几个工具类,例如Imageloadre,这里面就用到了builer模式
比如 需要在application中初始化 Imageloader对象的基本配置,
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.diskCacheFileNameGenerator(new Md5FileNameGenerator())
.diskCacheSize(50 * 1024 * 1024) // 50 Mb
.tasksProcessingOrder(QueueProcessingType.LIFO)
.writeDebugLogs() // Remove for release app
.build();
// Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(config);
有兴趣的可以看看 ImageLoaderConfiguration 类的源码,就用到该模式。
如果项目里面大量用到该模式,可以把一个公共的
public Nutrition builder(){
return new Nutrition(this);
}
抽取出来,写成接口,
public interface Builder<T> {
public T builder();
}
需要用到的类都实现该接口,方便管理,例如
public class Nutrition2 {
private int age;
private int height;
private String name;
public static class Builer implements Builder<Nutrition2>{
private int age;
private int height;
private String name;
public Builer setAge(int age) {
this.age = age;
return this;
}
public Builer setHeight(int height) {
this.height = height;
return this;
}
public Builer setName(String name) {
this.name = name;
return this;
}
@Override
public Nutrition2 builder() {
return new Nutrition2(this);
}
}
private Nutrition2(Builer builder) {
age = builder.age;
height = builder.height;
name = builder.name;
}
}
builder类实现接口,泛型里面加入外部类的名字,就完成了。
说到图片下载,比较早的一个工具类 xUtils里面有另外一种写法,写一个简单的例子,仅供参考
public class Nutrition {
private int age;
private int height;
private String name;
public Nutrition setAge(int age) {
this.age = age;
return this;
}
public Nutrition setHeight(int height) {
this.height = height;
return this;
}
public Nutrition setName(String name) {
this.name = name;
return this;
}
}
创建对象时,Nutrition nur = new Nutrition().setAge(12).setHeight(175).setName("Tom");
这个原理和javabean原理一样,相当于是javabena的精炼版,是先产生空白对象,然后赋值,也有javabean的缺陷。
如果类的属性超过四个,建议采用Builder模式