最近开发任务中碰到一个非常好用的模式,那就是builder设计模式(即建造者设计模式)。
说到builder设计模式,常常会跟可重叠构造器和javabeans模式一起比较说明。下面分别讨论:
一. 可重叠构造器模式
可重叠构造器的意思就是有很多的构造器,只是参数个数,参数类型不一样。举个到处都在用的例子把:
package com.test.b;public class Person { //必要参数 private int id; private String name; //可选参数 private int age; private String sex; private String phone; public Person(int id,String name) { this(id,name,0); } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", phone=" + phone + "]"; } 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,0,"",""); } public Person(int id,String name,int age,String sex,String phone) { this.id=id; this.name=name; this.age=age; this.sex=sex; this.phone=phone; } }
虽然测试的时候,只传入了name和id就可以拿到对象,但是最终打印出来的确是很多参数的一个Person。很多参数的值还不符合常理,需要我们去处理。因此并不方便。这样的话,我们又不得不传入更多的参数,可是,我们只想用name和id两个参数。当然,也可以不用this,就写很多的构造器,但是参数个数不同而带来的构造器个数不同,者会导致太多的构造器,不好区分。有些参数都是string,还容易传错值,易混淆。
二. javabeans模式
package com.test.b;import java.io.Serializable;public class Person implements Serializable{ //必要参数 private int id; private String name; //可选参数 private int age; private String sex; private String phone; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
对于程序可读性以及参数的可控性的考虑我们会是会用javabean来进行类实例化和属性的赋值。
在使用javabean的时候,尤其是多线程时候,获取同一个javabean(可以通过序列/反序列获取),那么下面模拟一个场景:
线程A: 获取person,对其name age sex 就行set操作 同样线程B: 获取person,对其进行get操作 这时候会出现一种情况,在线程A中没有set完毕,线程B 就开始取相应的属性三. builder设计模式
package com.test.b;import java.io.Serializable;public class Person implements Serializable { // 必要参数 private int id; private String name; // 可选参数 private int age; private String sex; private String phone; public Person(Builder builder) { this.id = builder.id; this.name = builder.name; this.age = builder.age; this.sex = builder.sex; this.phone = builder.phone; } public int getId() { return id; } public String getName() { return name; } public int getAge() { return age; } public String getSex() { return sex; } public String getPhone() { return phone; } public static class Builder { private int id; private String name; private int age; private String sex; private String phone; public Builder setId(int id) { this.id = id; return this; } public Builder setName(String name) { this.name = name; return this; } public Builder setAge(int age) { this.age = age; return this; } public Builder setSex(String sex) { this.sex = sex; return this; } public Builder setPhone(String phone) { this.phone = phone; return this; } public Person build() { return new Person(this); } }} NOTE:最终使用的时候 Person person=new Person.Builder().set....().build()方式来得到person对象
在建造者模式中,提供一个辅助的静态建造器builder,可以在里面set Person的属性,与javaBean不同的是,建造者是先set,在通过build实例化person,这样既可以提高代码的阅读性,也可以防止对象没有实例化,就被调用;不会造成不一致性,同时解决了javabean模式的线程安全问题;
四. 比较
重叠构造器模式 | 形式简单 | 容易出错,参数表太长不容易控制,而且难以阅读 |
javaBean模式 | 容易阅读,创建实例比较容易 | 构造过程被分割到好多个set中容易造成线程不安全,导致对象处于不一致的状态 |
Builder模式 | 代码容易编写 | 创建对象,必须先创造构建器,造成一定的性能上的开销 |