Java设计中的Builder模式的介绍
概述
builder模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
使用场景
- 相同的方法,不同的执行顺序,产生不同的事件结果
- 多个部件或零件,都可以装配到一个对象中,但产生的运行结果又不相同时
- 产品类非常复杂,或者产品类中的调用顺序不同产生不同的作用
- 当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时
下面从一个person例子进行分析重叠构造器模式、javabeans模式、builder模式的使用。person类有两个必要参数(id和name),有5个可选参数(age,sex,phone,address和desc)
重叠构造器模式
在这种模式下,你提供第一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,依此类推,最后一个构造器包含所有的可选参数。下面看看其编程实现:
/ * 使用重叠构造器模式 */ public class person { //必要参数 private final int id; private final string name; //可选参数 private final int age; private final string sex; private final string phone; private final string address; private final string desc; public person(int id, string name) { this(id, name, 0); } public person(int id, string name, int age) { this(id, name, age, ""); } public person(int id, string name, int age, string sex) { this(id, name, age, sex, ""); } public person(int id, string name, int age, string sex, string phone) { this(id, name, age, sex, phone, ""); } public person(int id, string name, int age, string sex, string phone, string address) { this(id, name, age, sex, phone, address, ""); } public person(int id, string name, int age, string sex, string phone, string address, string desc) { this.id = id; this.name = name; this.age = age; this.sex = sex; this.phone = phone; this.address = address; this.desc = desc; } }
从上面的代码中,当你想要创建实例的时候,就利用参数列表最短的构造器,但该列表中包含了要设置的所有参数:
person person = new persion(1, "李四", 20, "男", "18800000000", "china", "测试使用重叠构造器模式");
重叠构造器可行,但是当有许多参数的时候,创建使用代码会很难写,并且较难以阅读
javabeans模式
采用javabean 的写法,写一堆属性的setter方法,通过生成对象,让后调用setter方法给属性赋值。
/ * 使用javabeans模式 */ public class person { //必要参数 private int id; private string name; //可选参数 private int age; private string sex; private string phone; private string address; private string desc; public void setid(int id) { this.id = id; } public void setname(string name) { this.name = name; } public void setage(int age) { this.age = age; } public void setsex(string sex) { this.sex = sex; } public void setphone(string phone) { this.phone = phone; } public void setaddress(string address) { this.address = address; } public void setdesc(string desc) { this.desc = desc; }
这种模式弥补了重叠构造器模式的不足。创建实例很容易,这样产生的代码读起来也很容易:
person person = new person(); person.setid(1); person.setname("李四"); person.setage(20); person.setsex("男"); person.setphone("18800000000"); person.setaddress("china"); person.setdesc("测试使用javabeans模式");
javabeans模式因为构造过程被分到了几个调用中,在构造过程中javabean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。
builder模式
builder模式既能保证像重叠构造器那样的安全,也能实现javabean模式那样的可读性。
/** * 使用builder模式 */ public class person { //必要参数 private final int id; private final string name; //可选参数 private final int age; private final string sex; private final string phone; private final string address; private final string desc; private person(builder builder) { this.id = builder.id; this.name = builder.name; this.age = builder.age; this.sex = builder.sex; this.phone = builder.phone; this.address = builder.address; this.desc = builder.desc; } public static class builder { //必要参数 private final int id; private final string name; //可选参数 private int age; private string sex; private string phone; private string address; private string desc; public builder(int id, string name) { this.id = id; this.name = name; } public builder age(int val) { this.age = val; return this; } public builder sex(string val) { this.sex = val; return this; } public builder phone(string val) { this.phone = val; return this; } public builder address(string val) { this.address = val; return this; } public builder desc(string val) { this.desc = val; return this; } public person build() { return new person(this); } } }
person是不可变得,所有的默认参数值都单独放在一个地方。builder的setter方法返回builder本身,以便可以链式调用。下面是客户端使用代码:
person person = new person.builder(1, "张三")
.age(18).sex("男").desc("测试使用builder模式").build();
android源码中的builder模式
- alertdialog源码
- universal-image-loader图片库
- okhttp的request源码
优点:
- 良好的封装性,使用建造者模式可以使客户端不比知道产品内部组成的细节
- 建造者独立,容易扩展(可通过抽象———接口,抽象类)
缺点:
- 会产生多余的builder对象以及director对象,消耗内存
总结 :builder模式通常作为配置类的构建器将配置的构建和表示分离开来,同时也是将配置从目标类中隔离出来,避免过多的setter方法。
下一篇: mysql5.6搭建主从复制