建立型設計模式 -- 建造者模式
一、小案例分析
1、功能需求:
現需要建房子,建房流程:挖地基、砌牆、封頂。對于不同種類的房子(高樓,别墅),流程雖然一樣,但是具體功能實作不同。如何實作建房子?
2、小菜雞的答案:
(1)定義一個抽象接口,并定義三個抽象方法(挖地基、砌牆、封頂)。
(2)對于不同種類的房子,實作該接口,并重寫相關方法即可。
(3)代碼實作:
package builder.pattern;/**
* 測試類
* */public class BuilderDemo { public static void main(String[] args) {
System.out.println("建别墅流程:");
BuilderHouse villa = new Villa();
System.out.println("\n建高樓流程");
BuilderHouse highBuild = new HighBuild();
}
}/**
* 定義一個建房子的接口,并定義其流程 */interface BuilderHouse { void scoopHole(); // 挖地基
void buildWall(); // 砌牆
void topOff(); // 封頂}/**
* 建别墅,實作建房子的接口
* */class Villa implements BuilderHouse { /**
* 建别墅流程 */
public Villa() {
scoopHole();
buildWall();
topOff();
}
@Override public void scoopHole() {
System.out.println("挖10米地基");
}
@Override public void buildWall() {
System.out.println("砌10層牆");
}
@Override public void topOff() {
System.out.println("樓頂建個遊泳池");
}
}/**
* 建高樓流程,實作建房子的接口
* */class HighBuild implements BuilderHouse { /**
* 建高樓流程 */
public HighBuild() {
scoopHole();
buildWall();
topOff();
}
@Override public void scoopHole() {
System.out.println("挖30米地基");
}
@Override public void buildWall() {
System.out.println("砌60層牆");
}
@Override public void topOff() {
System.out.println("樓頂建個停機坪");
}
}
(4)代碼分析:
容易了解并操作,但是程式的擴充性不好,且耦合性強(将産品與建立産品的過程封裝在一起)。
(5)UML圖

二、建造者模式
1、什麼是建造者模式
又叫生成器模式,其将複雜的對象的建造過程抽象出來,并在其子類中去實作不同的建造。使用者隻需要去調用就行,不需要管建造的内部細節如何實作。簡單的了解為,将一堆零件拼成一個整體,而零件是抽象的,并由不同的子類去實作,使用者不需要管零件是如何形成的,能組裝就行。
2、建造者模式的核心角色
(1)産品(Product):一個具體的産品對象。
(2)抽象建造者(Builder):定義一個接口或抽象類,内部定義生成産品各個零件的抽象方法。
(3)具體建造者(ConcreateBuilder):實作接口,并重寫生成各零件的方法。
(4)組裝者(Commander):按照流程拼接零件,并傳回一個對象。
(5)代碼實作:
package builder.pattern;/**
* 測試類
* */public class BuilderDemo { public static void main(String[] args) {
System.out.println("建别墅流程:");
HouseBuilder villaBuilder = new VillaBuilder();
HouseCommandar villaCommandar = new HouseCommandar(villaBuilder);
System.out.println(villaCommandar.createHouse());
System.out.println("\n建高樓流程");
HouseBuilder highBuildBuilder = new HighBuildBuilder();
HouseCommandar highBuildCommandar = new HouseCommandar(highBuildBuilder);
System.out.println(highBuildCommandar.createHouse());
}
}/**
* 産品類
* */class House { private String basis; private String wall; private String roof; public String getBasis() { return basis;
} public void setBasis(String basis) { this.basis = basis;
} public String getWall() { return wall;
} public void setWall(String wall) { this.wall = wall;
} public String getRoof() { return roof;
} public void setRoof(String roof) { this.roof = roof;
}
@Override public String toString() { return "House [basis=" + basis + ", wall=" + wall + ", roof=" + roof + "]";
}
}/**
* 抽象建造者,内部定義生成産品各個零件的抽象方法。
* */abstract class HouseBuilder {
House house = new House(); public abstract void scoopHole(); // 挖地基
public abstract void buildWall(); // 砌牆
public abstract void topOff(); // 封頂
public House getHouse() { return house;
}
}/**
* 具體建造者,建别墅,繼承抽象類,并重寫相關方法
* */class VillaBuilder extends HouseBuilder {
@Override public void scoopHole() {
house.setBasis("挖10米地基");
}
@Override public void buildWall() {
house.setWall("砌10層牆");
}
@Override public void topOff() {
house.setRoof("樓頂建個遊泳池");
}
}/**
* 建高樓流程,實作建房子的接口
* */class HighBuildBuilder extends HouseBuilder {
@Override public void scoopHole() {
house.setBasis("挖30米地基");
}
@Override public void buildWall() {
house.setWall("砌60層牆");
}
@Override public void topOff() {
house.setRoof("樓頂建個停機坪");
}
}/**
* 組裝者,控制零件組合流程,并傳回一個産品對象 */class HouseCommandar { private HouseBuilder houseBuilder; /**
* 擷取具體的建造者 */
public HouseCommandar(HouseBuilder houseBuilder) { this.houseBuilder = houseBuilder;
} /**
* 控制建房流程,并傳回一個房子執行個體
*
* @return 房子執行個體 */
public House createHouse() {
houseBuilder.scoopHole();
houseBuilder.buildWall();
houseBuilder.topOff(); return houseBuilder.getHouse();
}
}
(6)代碼分析:
相比于上例,其将控制産品流程的代碼抽出來了。使産品與産品建構流程分離,進而在一定程度上解耦。當擴充代碼時,隻需繼承HouseBuilder 并重寫相關方法即可。
(7)UML圖:
3、抽象工廠模式與建造者模式的差別
(1)抽象工廠模式是根據不同的工廠去建立一個對象。
(2)建造者模式是根據流程去組裝一個對象。
三、JDK源碼分析(StringBuilder)
1、部分源碼
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
}abstract class AbstractStringBuilder implements Appendable, CharSequence{ //内部定義了一系列方法,且部分方法傳回值類型為AbstractStringBuilder
public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len; return this;
} public AbstractStringBuilder deleteCharAt(int index) { if ((index < 0) || (index >= count)) throw new StringIndexOutOfBoundsException(index);
System.arraycopy(value, index+1, value, index, count-index-1);
count--; return this;
}
}