流水作業大家應該都清楚吧!在流水作業中,我們可以將一些復雜的東西給構建出來,例如汽車。我們都知道汽車內部構件比較復雜,由很多部件組成,例如車輪、車門、發動機、方向盤等等,對於我們用戶來說我們並不需要知道這個汽車是如何構建出來的,它的各個部件是如何組裝,我們只需要知道一點:這是一輛完整的汽車。同樣KFC也是這樣的,在KFC中我們吃套餐也不需要知道這個套餐是怎樣做出來的,我們只需要在店里面向服務員點就可以得到相應的套餐了。對於這兩個例子我們通過指定某個對象類型就可以得到一個完整的對象,而無須關心其內部的構建。
在軟件開發中,也會存在一些構造非常復雜的對象,這些對象擁有一系列的成員屬性,這些成員屬性有些是基本數據類型,有些是引用類型,總之就是一句話,這個對象的構建比較復雜。在這里我們就將復雜對象當做汽車,成員屬性當做部件,對象的構建當做汽車的組合。對於用戶而言我們總是希望我們在使用對象時足夠簡單,如果一個復雜的對象直接丟給用戶,用戶會是痛苦不堪的(給你一堆部件,你來組裝成一輛汽車看看),除了這個構建的過程外,可能用戶會忘記某些成員屬性。所以我們就希望能夠像使用汽車一樣使用復雜的對象:直接告訴你我需要的對象名或者對象類型,你返回一個完成的對象實例給我。建造者返回給客戶一個完整的的產品對象,而客戶端無須關心該對象所包含的額屬性和組建方式,這就是建造者模式的設計動機。
一、模式定義
建造者模式將一個復雜對象的構建與表示分離,使得同樣的構建過程可以創建不同的表示。
建造者模式構建復雜對象就像造汽車一樣,是一個一個組件一個一個步驟創建出來的,它允許用戶通過制定的對象類型和內容來創建他們,但是用戶並不需要知道這個復雜對象是如何構建的,它只需要明白通過這樣做我可以得到一個完整的復雜對象實例。
二、模式結構
建造者模式的UML結構圖:
建造者模式主要包含四個角色:
Builder:抽象建造者。它聲明為創建一個Product對象的各個部件指定的抽象接口。
ConcreteBuilder:具體建造者。實現抽象接口,構建和裝配各個部件。
Director:指揮者。構建一個使用Builder接口的對象。它主要是用於創建一個復雜的對象,它主要有兩個作用,一是:隔離了客戶與對象的生產過程,二是:負責控制產品對象的生產過程。
Product:產品角色。一個具體的產品對象。
三、模式實現
KFC里面一般都有好幾種可供客戶選擇的套餐,它可以根據客戶所點的套餐,然后在后面做這些套餐,返回給客戶的事一個完整的、美好的套餐。下面我們將會模擬這個過程,我們約定套餐主要包含漢堡、薯條、可樂、雞腿等等組成部分,使用不同的組成部分就可以構建出不同的套餐。
public class Meal {
private String food;
private String drink;
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
}
然后是套餐構造器:MealBuilder.java
public abstract class MealBuilder {
Meal meal = new Meal();
public abstract void buildFood();
public abstract void buildDrink();
public Meal getMeal(){
return meal;
}
}
然后是套餐A、套餐B。這個兩個套餐都是實現抽象套餐類。
public class MealA extends MealBuilder{
public void buildDrink() {
meal.setDrink("一杯可樂");
}
public void buildFood() {
meal.setFood("一盒薯條");
}
}
public class MealB extends MealBuilder{
public void buildDrink() {
meal.setDrink("一杯檸檬果汁");
}
public void buildFood() {
meal.setFood("三個雞翅");
}
}
public class KFCWaiter {
private MealBuilder mealBuilder;
public void setMealBuilder(MealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}
public Meal construct(){
//准備食物
mealBuilder.buildFood();
//准備飲料
mealBuilder.buildDrink();
//准備完畢,返回一個完整的套餐給客戶
return mealBuilder.getMeal();
}
}
測試類
public class Client {
public static void main(String[] args) {
//服務員
KFCWaiter waiter = new KFCWaiter();
//套餐A
MealA a = new MealA();
//服務員准備套餐A
waiter.setMealBuilder(a);
//獲得套餐
Meal mealA = waiter.construct();
System.out.print("套餐A的組成部分:");
System.out.println(mealA.getFood()+"---"+mealA.getDrink());
}
}
運行結果:
套餐A的組成部分:一盒薯條---一杯可樂
四、模式優缺點
優點
1、將復雜產品的創建步驟分解在不同的方法中,使得創建過程更加清晰,使得我們能夠更加精確的控制復雜對象的產生過程。
2、將產品的創建過程與產品本身分離開來,可以使用相同的創建過程來得到不同的產品。也就說細節依賴抽象。
3、每一個具體建造者都相對獨立,而與其他的具體建造者無關,因此可以很方便地替換具體建造者或增加新的具體建造者,用戶使用不同的具體建造者即可得到不同的產品對象。
缺點
1、建造者模式所創建的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用范圍受到一定的限制。
2、如果產品的內部變化復雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。
五、模式適用場景
1、需要生成的產品對象有復雜的內部結構,這些產品對象通常包含多個成員屬性。
2、隔離復雜對象的創建和使用,並使得相同的創建過程可以創建不同的產品。
六。模式總結
1、建造者模式是將一個復雜對象的創建過程給封裝起來,客戶只需要知道可以利用對象名或者類型就能夠得到一個完整的對象實例,而不需要關心對象的具體創建過程。
2、建造者模式將對象的創建過程與對象本身隔離開了,使得細節依賴於抽象,符合依賴倒置原則。可以使用相同的創建過程來創建不同的產品對象。