建造者模式屬于創(chuàng)建型模式,提供了一種創(chuàng)建對象的最佳方式。
定義:將一個復(fù)雜對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
主要作用:在用戶不知道對象的建造過程和細(xì)節(jié)的情況下就可以直接創(chuàng)建復(fù)雜的對象。
建造者模式的四個對象

Product產(chǎn)品類:
通常是實現(xiàn)了模板方法模式(這里可以后續(xù)看我的更新博客,如果我更新了),也就是有模板方法和基本方法。
Builder抽象建造者:
規(guī)范產(chǎn)品的組建,一般是由子類實現(xiàn)。
ConcreteBuilder具體建造者:
實現(xiàn)抽象類定義的所有方法,并且返回一個組建好的對象。
Director導(dǎo)演類:
負(fù)責(zé)安排已有模塊的順序,然后告訴Builder開始建造。
例子
舉個例子:
- 工廠(建造者模式):負(fù)責(zé)制造汽車(組裝過程和細(xì)節(jié)在工廠內(nèi))
- 汽車購買者(用戶):你只要說出你需要的型號(對象的類型和內(nèi)容),然后直接購買就可以使用了(不需要知道汽車是怎么組裝的(比如車輪,車門,發(fā)動機,方向盤等等))
同樣的,我們以這個例子用代碼來實現(xiàn)一下更能清晰的了解。
我們的汽車類(Car),也就是我們的產(chǎn)品
package builder;
public abstract class Builder {
private String wheel; //車輪
private String carDoor; //車門
private String engine; //發(fā)動機
private String steeringWheel; //方向盤
...我們的get和set方法(為了簡潔,我就不展示了)...
@Override
public String toString() {
return "Builder{" +
"wheel='" + wheel + '\'' +
", carDoor='" + carDoor + '\'' +
", engine='" + engine + '\'' +
", steeringWheel='" + steeringWheel + '\'' +
'}';
}
}
我們的建造抽象類(Builder)
package builder;
public abstract class Builder {
abstract void buildWheel(); //建造車輪
abstract void buildCarDoor(); //建造車門
abstract void buildEngine(); //建造發(fā)動機
abstract void buildSteeringWheel(); //建造方向盤
//建造完成,獲得車輛
abstract Car getCar();
}
我們的建造實現(xiàn)類(ConcreteBuilder)
package builder;
public class ConcreteBuilder extends Builder{
private Car car;
//定義一個空構(gòu)造方法,在實例化的同時實例我們的車
public ConcreteBuilder(){
car = new Car();
}
@Override
void buildWheel() {
car.setWheel("輪子");
}
@Override
void buildCarDoor() {
car.setCarDoor("車門");
}
@Override
void buildEngine() {
car.setEngine("發(fā)動機");
}
@Override
void buildSteeringWheel() {
car.setSteeringWheel("方向盤");
}
@Override
Car getCar() {
return car;
}
}
我們的導(dǎo)演類(Director),用來指揮我們的創(chuàng)建過程,比如創(chuàng)建順序
package builder;
public class Director {
public Car carBuilder(Builder builder){
//按照我們的導(dǎo)演的順序來創(chuàng)建車輛
builder.buildWheel();
builder.buildCarDoor();
builder.buildEngine();
builder.buildSteeringWheel();
//創(chuàng)建完之后,返回我們創(chuàng)建完的車輛
return builder.getCar();
}
}
我們在測試類中測試一下
package builder;
public class Test {
public static void main(String[] args) {
//創(chuàng)建一個我們的導(dǎo)演,指揮
Director director = new Director();
//導(dǎo)演指揮我們具體的實現(xiàn)類去創(chuàng)建車輛
Car car = director.carBuilder(new ConcreteBuilder());
System.out.println(car.toString());
}
}
//測試結(jié)果
Car{wheel='輪子', carDoor='車門', engine='發(fā)動機', steeringWheel='方向盤'}
Process finished with exit code 0
可以看到,通過這樣的建造者模式,我們的復(fù)雜過程被我們封裝了起來。但是我們也發(fā)現(xiàn)了我們的導(dǎo)演可以指揮順序,但是里面具體的參數(shù),比如想建造什么無法修改。其實也可以,我們對導(dǎo)演類進(jìn)行擴展一下就行。
我們通過靜態(tài)內(nèi)部類實現(xiàn)零件無序裝配構(gòu)造,這種方式使用更加靈活,更符合定義。使用的時候可以根據(jù)用戶需求自定義更改內(nèi)容。我們對其修改后,示例代碼如下:
我們對抽象建造的抽象方法添加了傳遞參數(shù),修改了返回類型
package builder;
public abstract class Builder {
abstract Builder buildWheel(String msg); //建造車輪
abstract Builder buildCarDoor(String msg); //建造車門
abstract Builder buildEngine(String msg); //建造發(fā)動機
abstract Builder buildSteeringWheel(String msg); //建造方向盤
//建造完成,獲得車輛
abstract Car getCar();
}
然后在實現(xiàn)類進(jìn)行實現(xiàn)
package builder;
public class ConcreteBuilder extends Builder{
private Car car;
//定義一個空構(gòu)造方法,在實例化的同時實例我們的車
public ConcreteBuilder(){
car = new Car();
}
@Override
Builder buildWheel(String msg) {
car.setWheel(msg);
return this;
}
@Override
Builder buildCarDoor(String msg) {
car.setCarDoor(msg);
return this;
}
@Override
Builder buildEngine(String msg) {
car.setEngine(msg);
return this;
}
@Override
Builder buildSteeringWheel(String msg) {
car.setSteeringWheel(msg);
return this;
}
@Override
Car getCar() {
return car;
}
}
這時我們在導(dǎo)演類里面,就可以自由的傳遞我們需要的參數(shù)來建造車輛,也可以指定順序。
package builder;
public class Director {
public Car carBuilder(Builder builder){
//創(chuàng)建自定義車輛,自定義建造順序
return builder.buildWheel("厲害的車輪")
.buildCarDoor("漂亮的車門")
.buildEngine("馬力十足的引擎")
.buildSteeringWheel("舒服的方向盤")
.getCar();
}
}
測試類的測試結(jié)果
Car{wheel='厲害的車輪', carDoor='漂亮的車門', engine='馬力十足的引擎', steeringWheel='舒服的方向盤'}
Process finished with exit code 0
總結(jié)
建造者模式關(guān)注的是零件類型和裝配順序,我們可以總結(jié)一下它的優(yōu)缺點和使用場景。
優(yōu)點:
- 封裝性:產(chǎn)品的建造和表示分離,實現(xiàn)了解耦。使用建造者模式可以使客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié)。
- 建造者獨立,容易擴展:具體的建造者之間是相互獨立的,這有利于系統(tǒng)的擴展,增加新的具體建造者無需修改原有類庫的代碼,符合”符合開閉原則“。
- 便于控制細(xì)節(jié)風(fēng)險:由于具體的建造者是獨立的,因此可以對建造過程逐步細(xì)化,而不對其他的模塊產(chǎn)生任何影響。
缺點:
- 建造者模式所創(chuàng)建的產(chǎn)品一般具有較多的共同點,其組成部分相似;如果產(chǎn)品之間
差異性很大,則不適合使用建造者模式,因此其使用范圍受到一定的限制。
- 如果產(chǎn)品的內(nèi)部變化復(fù)雜,可能會導(dǎo)致需要定義很多具體建造者類來實現(xiàn)這種變化,導(dǎo)致系統(tǒng)變得很龐大。
使用場景:
- 需要生成的產(chǎn)品對象有復(fù)雜的內(nèi)部結(jié)構(gòu),這些產(chǎn)品對象具備共性
- 隔離復(fù)雜對象的創(chuàng)建和使用,并使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品
- 適合于一個具有較多的零件(屬性)的產(chǎn)品(對象)的創(chuàng)建過程
補充:
通過學(xué)習(xí)建造者模式,我們可以發(fā)現(xiàn)這與我們的抽象工廠模式很是相像,但是也是有不同的地方。(關(guān)于工廠模式可以看我的設(shè)計模式詳解之工廠模式)
- 與抽象工廠相比,建造者模式返回一個組裝好的完整產(chǎn)品,而抽象工廠模式返回一系列相關(guān)的產(chǎn)品,這些產(chǎn)品位于不同的產(chǎn)品等級結(jié)構(gòu),構(gòu)成了一個產(chǎn)品族。
- 在抽象工廠模式中,客戶端示例工廠類,然后調(diào)用工廠方法獲取所需產(chǎn)品對象,而在建造者模式中,客戶端不可以直接調(diào)用建造者的相關(guān)方法,而是通過導(dǎo)演類來指導(dǎo)如何生成對象,包括對象的組裝過程和建造順序,它側(cè)重于一步步構(gòu)造一個復(fù)雜對象,返回一個完整的對象。
- 如果將抽象工廠看成汽車配件生產(chǎn)工廠,生產(chǎn)一個產(chǎn)品族的的產(chǎn)品,那么建造者模式就是一個汽車組裝工廠,通過對部件組裝可以返回一輛完整的汽車。
建造者模式最主要的功能是基本方法的調(diào)用順序安排,因為組裝順序不同對象效能也不同,這才是建造者模式要表達(dá)的核心意義。
參考資料
(書籍)大話設(shè)計模式
(視頻)遇見狂神說:通俗易懂的23種設(shè)計模式教學(xué)