书接上文,这次来讲讲另一个生成对象的模式,建造者模式。什么是建造者模式?在面向对象语言中,一个对象的产生都要先经过构造器构造参数,参数可有可无,可多可少,根据需要来定。但是如果一个类中定义的内部变量个数很多,需要又不能确定的话,这时写起代码来就比较麻烦。所以建造者模式就是把对象的构建过程和使用分离开来,达到丁是丁卯是卯的效果,清晰方便。话不多说,上菜。
class MyHome {
private String mDoor;
private String mKitchen;
private String mToilet;
private String mBathroom;
private String mStudy;
public String getDoor() {
return mDoor;
}
public void setDoor(String mDoor) {
this.mDoor = mDoor;
}
public String getKitchen() {
return mKitchen;
}
public void setKitchen(String mKitchen) {
this.mKitchen = mKitchen;
}
public String getToilet() {
return mToilet;
}
public void setToilet(String mToilet) {
this.mToilet = mToilet;
}
public String getBathroom() {
return mBathroom;
}
public void setBathroom(String mBathroom) {
this.mBathroom = mBathroom;
}
public String getStudy() {
return mStudy;
}
public void setStudy(String mStudy) {
this.mStudy = mStudy;
}
public MyHome() {
}
@Override
public String toString() {
return "MyHome [mDoor=" + mDoor + ", mKitchen=" + mKitchen
+ ", mToilet=" + mToilet + ", mBathroom=" + mBathroom
+ ", mStudy=" + mStudy + "]";
}
}
interface Builder{
Builder planningDoor(String door);
Builder planningKitchen(String kitchen);
Builder planningToilet(String toilet);
Builder planningBathroom(String bathroom);
Builder planningStudy(String study);
MyHome build();
}
class HomeBuilder implements Builder{
private MyHome mMyHome = new MyHome();
@Override
public MyHome build() {
return mMyHome;
}
@Override
public HomeBuilder planningDoor(String door) {
mMyHome.setDoor(door);
return this;
}
@Override
public HomeBuilder planningKitchen(String kitchen) {
mMyHome.setKitchen(kitchen);
return this;
}
@Override
public HomeBuilder planningToilet(String toilet) {
mMyHome.setToilet(toilet);
return this;
}
@Override
public HomeBuilder planningBathroom(String bathroom) {
mMyHome.setBathroom(bathroom);
return this;
}
@Override
public HomeBuilder planningStudy(String study) {
mMyHome.setStudy(study);
return this;
}
}
public class Home {
public static void main(String[] args) {
Builder homeBuilder = new HomeBuilder();
MyHome myHome = homeBuilder
.planningBathroom("浴室")
.planningDoor("门")
.planningKitchen("厨房")
.planningToilet("厕所")
.build();
System.out.println(myHome.toString());
}
}
这样一个对象就生成了,参数个数可以根据自己需要来设置。
这是个简单的例子,jdk的StringBuilder类就使用了建造者模式,我把StringBuilder的几个重要方法提取出来新写个类。
class CharArrayBuilder {
char[] value;
int count;
public CharArrayBuilder(){
}
public CharArrayBuilder(int capacity) {
value = new char[capacity];
}
public int length() {
return count;
}
public int capacity() {
return value.length;
}
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
}
private void ensureCapacityInternal(int minimumCapacity) {
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}
public CharArrayBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
public CharArrayBuilder append(CharArray ca) {
if (ca == null)
return append("null");
int len = ca.length();
ensureCapacityInternal(count + len);
ca.getChars(0, len, value, count);
count += len;
return this;
}
public CharArrayBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin){
if (srcBegin < 0)
throw new StringIndexOutOfBoundsException(srcBegin);
if ((srcEnd < 0) || (srcEnd > count))
throw new StringIndexOutOfBoundsException(srcEnd);
if (srcBegin > srcEnd)
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
}
class CharArray extends CharArrayBuilder{
public CharArray() {
super(16);
}
public CharArray(int capacity) {
super(capacity);
}
public CharArray(String str) {
super(str.length() + 16);
append(str);
}
public CharArray append(Object obj) {
return append(String.valueOf(obj));
}
public CharArray append(String str) {
super.append(str);
return this;
}
public CharArray append(CharArray ca) {
if (ca == null)
return append("null");
int len = ca.length();
int newcount = count + len;
if (newcount > value.length)
expandCapacity(newcount);
ca.getChars(0, len, value, count);
count = newcount;
return this;
}
public CharArray append(char[] str) {
super.append(str);
return this;
}
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
}
public class Client {
public static void main(String[] args) {
CharArray charArray = new CharArray();
charArray.append("abcdefg").append("123");
System.out.println(charArray.capacity());
System.out.println(charArray.length());
System.out.println(charArray);
}
}
相同的点是都return this,直接返回当前对象,然后继续操作。