建造者模式:深入理解建造者模式 ——組裝復(fù)雜的實(shí)例

目錄:

一 建造者模式介紹

1.1 定義

1.2 為什么要用建造者模式(優(yōu)點(diǎn))?

1.3 哪些情況不要用建造者模式(缺點(diǎn))?

1.4 抽象工廠模式VS建造者模式

1.4 模式結(jié)構(gòu)

  • 1.4.1 建造者模式的UML結(jié)構(gòu)圖
  • 1.4.2 建造者模式主要包含四個(gè)角色

二 建造者模式分析

三 實(shí)例:KFC套餐

  • 1)Product(產(chǎn)品角色)
  • 2)Builder(抽象建造者)
  • 3)ConcreteBuilder(具體建造者)
  • 4)Director(指揮者)
  • 5)測(cè)試類(lèi)(客戶(hù)端類(lèi))

四 總結(jié)

無(wú)論是在現(xiàn)實(shí)世界中還是在軟件系統(tǒng)中,都存在一些復(fù)雜的對(duì)象,它們擁有多個(gè)組成部分,如汽車(chē),它包括車(chē)輪、方向盤(pán)、發(fā)送機(jī)等各種部件。而對(duì)于大多數(shù)用戶(hù)而言,無(wú)須知道這些部件的裝配細(xì)節(jié),也幾乎不會(huì)使用單獨(dú)某個(gè)部件,而是使用一輛完整的汽車(chē),可以通過(guò)建造者模式對(duì)其進(jìn)行設(shè)計(jì)與描述,建造者模式可以將部件和其組裝過(guò)程分開(kāi),一步一步創(chuàng)建一個(gè)復(fù)雜的對(duì)象。用戶(hù)只需要指定復(fù)雜對(duì)象的類(lèi)型就可以得到該對(duì)象,而無(wú)須知道其內(nèi)部的具體構(gòu)造細(xì)節(jié).

50439782.jpg

一 建造者模式介紹

1.1 定義

建造者模式(Builder Pattern) 又名生成器模式,是一種對(duì)象構(gòu)建模式。它可以將復(fù)雜對(duì)象的建造過(guò)程抽象出來(lái)(抽象類(lèi)別),使這個(gè)抽象過(guò)程的不同實(shí)現(xiàn)方法可以構(gòu)造出不同表現(xiàn)(屬性)的對(duì)象。

建造者模式 是一步一步創(chuàng)建一個(gè)復(fù)雜的對(duì)象,它允許用戶(hù)只通過(guò)指定復(fù)雜對(duì)象的類(lèi)型和內(nèi)容就可以構(gòu)建它們,用戶(hù)不需要知道內(nèi)部的具體構(gòu)建細(xì)節(jié)。

68223661.jpg

1.2 為什么要用建造者模式(優(yōu)點(diǎn))?

  1. 客戶(hù)端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過(guò)程解耦,使得相同的創(chuàng)建過(guò)程可以創(chuàng)建不同的產(chǎn)品對(duì)象。

  2. 每一個(gè)具體建造者都相對(duì)獨(dú)立,而與其他的具體建造者無(wú)關(guān),因此可以很方便地替換具體建造者或增加新的具體建造者, 用戶(hù)使用不同的具體建造者即可得到不同的產(chǎn)品對(duì)象 。

  3. 可以更加精細(xì)地控制產(chǎn)品的創(chuàng)建過(guò)程 。將復(fù)雜產(chǎn)品的創(chuàng)建步驟分解在不同的方法中,使得創(chuàng)建過(guò)程更加清晰,也更方便使用程序來(lái)控制創(chuàng)建過(guò)程。

  4. 增加新的具體建造者無(wú)須修改原有類(lèi)庫(kù)的代碼,指揮者類(lèi)針對(duì)抽象建造者類(lèi)編程,系統(tǒng)擴(kuò)展方便,符合 “開(kāi)閉原則”

1.3 哪些情況不要用建造者模式(缺點(diǎn))?

  1. 產(chǎn)品之間差異性很大的情況:建造者模式所創(chuàng)建的產(chǎn)品一般具有較多的共同點(diǎn),其組成部分相似,如果產(chǎn)品之間的差異性很大,則不適合使用建造者模式,因此其使用范圍受到一定的限制。

  2. 產(chǎn)品內(nèi)部變化很復(fù)雜的情況: 如果產(chǎn)品的內(nèi)部變化復(fù)雜,可能會(huì)導(dǎo)致需要定義很多具體建造者類(lèi)來(lái)實(shí)現(xiàn)這種變化,導(dǎo)致系統(tǒng)變得很龐大。

1.4 抽象工廠模式VS建造者模式
抽象工廠模式實(shí)現(xiàn)對(duì)產(chǎn)品家族的創(chuàng)建,一個(gè)產(chǎn)品家族是這樣的一系列產(chǎn)品:具有不同分類(lèi)維度的產(chǎn)品組合,采用抽象工廠模式不需要關(guān)心構(gòu)建過(guò)程,只關(guān)心什么產(chǎn)品由什么工廠生產(chǎn)即可。而建造者模式則是要求按照指定的藍(lán)圖建造產(chǎn)品,它的主要目的是通過(guò)組裝零配件而產(chǎn)生一個(gè)新產(chǎn)品。

1.4 模式結(jié)構(gòu)

1.4.1 建造者模式的UML結(jié)構(gòu)圖


24724195.jpg

1.4.2 建造者模式主要包含四個(gè)角色
Product(產(chǎn)品角色):一個(gè)具體的產(chǎn)品對(duì)象。
Builder(抽象建造者):創(chuàng)建一個(gè)Product對(duì)象的各個(gè)部件指定的抽象接口。
ConcreteBuilder(具體建造者):實(shí)現(xiàn)抽象接口,構(gòu)建和裝配各個(gè)部件。
Director(指揮者):構(gòu)建一個(gè)使用Builder接口的對(duì)象。它主要是用于創(chuàng)建一個(gè)復(fù)雜的對(duì)象。它主要有兩個(gè)作用,一是:隔離了客戶(hù)與對(duì)象的生產(chǎn)過(guò)程,二是:負(fù)責(zé)控制產(chǎn)品對(duì)象的生產(chǎn)過(guò)程。

二 建造者模式分析
1 ) 一個(gè)典型的復(fù)雜對(duì)象其類(lèi)代碼示例如下:

public class Product 
{
private String partA; //可以是任意類(lèi)型
private String partB;
private String partC;
//partA的Getter方法和Setter方法省略
//partB的Getter方法和Setter方法省略
//partC的Getter方法和Setter方法省略
}

2 ) 抽象建造者類(lèi)中定義了產(chǎn)品的創(chuàng)建方法和返回方法,其典型代碼如下:

public abstract class Builder
{
protected Product product=new Product();

public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();

public Product getResult()
{
return product;
}
} 

3 ) 具體建造者。實(shí)現(xiàn)抽象接口,構(gòu)建和裝配各個(gè)部件,實(shí)例代碼如下:

public class ConcreteBuilder extends Builder{
public void buildPartA(){
...
}
public void buildPartB(){
...
}
public void buildPartC(){
...
}
}

4)指揮者類(lèi)的代碼示例如下:

建造者模式的結(jié)構(gòu)中還引入了一個(gè)指揮者類(lèi)Director,該類(lèi)的作用主要有兩個(gè):一方面它隔離了客戶(hù)與生產(chǎn)過(guò)程;另一方面它負(fù)責(zé)控制產(chǎn)品的生成過(guò)程。指揮者針對(duì)抽象建造者編程,客戶(hù)端只需要知道具體建造者的類(lèi)型,即可通過(guò)指揮者類(lèi)調(diào)用建造者的相關(guān)方法,返回一個(gè)完整的產(chǎn)品對(duì)象。

public class Director
{
private Builder builder;
//1 構(gòu)造方法的方式注入builder對(duì)象
public Director(Builder builder)
{
this.builder=builder;
}
//2 set方法注入builder對(duì)象
public void setBuilder(Builder builder)
{
this.builder=builer;
}

public Product construct()
{
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
} 

5 ) 客戶(hù)端類(lèi)代碼片段:

在客戶(hù)端代碼中,無(wú)須關(guān)心產(chǎn)品對(duì)象的具體組裝過(guò)程,只需確定具體建造者的類(lèi)型即可,建造者模式將復(fù)雜對(duì)象的構(gòu)建與對(duì)象的表現(xiàn)分離開(kāi)來(lái),這樣使得同樣的構(gòu)建過(guò)程可以創(chuàng)建出不同的表現(xiàn)。

……
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Product product = director.construct();
……

三 實(shí)例:KFC套餐

建造者模式可以用于描述KFC如何創(chuàng)建套餐:套餐是一個(gè)復(fù)雜對(duì)象,它一般包含主食(如漢堡、雞肉卷等)和飲料(如果汁、可樂(lè)等)等組成部分,不同的套餐有不同的組成部分,而KFC的服務(wù)員可以根據(jù)顧客的要求,一步一步裝配這些組成部分,構(gòu)造一份完整的套餐,然后返回給顧客。

58066865.jpg

1)Product(產(chǎn)品角色)
一個(gè)具體的產(chǎn)品對(duì)象。

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;
}
}

2)Builder(抽象建造者)
創(chuàng)建一個(gè)Product對(duì)象的各個(gè)部件指定的抽象接口。

public abstract class MealBuilder {
Meal meal = new Meal();

public abstract void buildFood();

public abstract void buildDrink();

public Meal getMeal(){
return meal;
}
}

3) ConcreteBuilder(具體建造者)
實(shí)現(xiàn)抽象接口,構(gòu)建和裝配各個(gè)部件。

A套餐:

public class MealA extends MealBuilder{

public void buildDrink() {
meal.setDrink("可樂(lè)");
}

public void buildFood() {
meal.setFood("薯?xiàng)l");
}

}

B套餐:

public class MealB extends MealBuilder{

public void buildDrink() {
meal.setDrink("檸檬果汁");
}

public void buildFood() {
meal.setFood("雞翅");
}

}

4)Director(指揮者)
構(gòu)建一個(gè)使用Builder接口的對(duì)象。它主要是用于創(chuàng)建一個(gè)復(fù)雜的對(duì)象,它主要有兩個(gè)作用,一是:隔離了客戶(hù)與對(duì)象的生產(chǎn)過(guò)程,二是:負(fù)責(zé)控制產(chǎn)品對(duì)象的生產(chǎn)過(guò)程。

public class KFCWaiter {
private MealBuilder mealBuilder;

public KFCWaiter(MealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}


public Meal construct(){
//準(zhǔn)備食物
mealBuilder.buildFood();
//準(zhǔn)備飲料
mealBuilder.buildDrink();

//準(zhǔn)備完畢,返回一個(gè)完整的套餐給客戶(hù)
return mealBuilder.getMeal();
}
}

5)測(cè)試類(lèi)(客戶(hù)端類(lèi))
public class Test {
public static void main(String[] args) {

//套餐A
MealA a = new MealA();
//準(zhǔn)備套餐A的服務(wù)員
KFCWaiter waiter = new KFCWaiter(a);
//獲得套餐
Meal mealA = waiter.construct();  
System.out.print("套餐A的組成部分:");
System.out.println("食物:"+mealA.getFood()+";   "+"飲品:"+mealA.getDrink());
}
}

輸出結(jié)果:

套餐A的組成部分:食物:薯?xiàng)l; 飲品:可樂(lè)
1
2

四 總結(jié)

本文首先介紹了建造者模型包括建造者模型的定義、為什么要用它、那些情況不適合使用這種模式以及抽象工廠模式和建造者模式的區(qū)別的簡(jiǎn)單分析。

然后通過(guò)建造者模式的四個(gè)角色的常見(jiàn)示例代碼,通過(guò)代碼層面分析了建造者模式。

最后通過(guò)一個(gè)KFC套餐實(shí)例,介紹了建造者模式在實(shí)例中的基本使用手段。

參考:

《設(shè)計(jì)模式之禪》

《圖解設(shè)計(jì)模式》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 沒(méi)有人買(mǎi)車(chē)會(huì)只買(mǎi)一個(gè)輪胎或者方向盤(pán),大家買(mǎi)的都是一輛包含輪胎、方向盤(pán)和發(fā)動(dòng)機(jī)等多個(gè)部件的完整汽車(chē)。如何將這些部件組...
    justCode_閱讀 2,010評(píng)論 1 6
  • 【學(xué)習(xí)難度:★★★★☆,使用頻率:★★☆☆☆】直接出處:建造者模式梳理和學(xué)習(xí):https://github.com...
    BruceOuyang閱讀 879評(píng)論 0 5
  • 模式動(dòng)機(jī) 無(wú)論是在現(xiàn)實(shí)世界中還是在軟件系統(tǒng)中,都存在一些復(fù)雜的對(duì)象,它們擁有多個(gè)組成部分,如汽車(chē),它包括車(chē)輪、方向...
    lijun_m閱讀 451評(píng)論 0 0
  • 1《環(huán)太平洋》美 很多年前在電影院看過(guò)這個(gè)電影,最近又翻出這個(gè)電影,只是在累的時(shí)候,看看這樣打怪獸的片子是一個(gè)很好...
    風(fēng)箏2017閱讀 457評(píng)論 0 0
  • 1 松一是一只被困在南方的北方松鼠。 在999年之前的一個(gè)風(fēng)雨交加的晚上,他匆忙藏好了準(zhǔn)備越冬的食物之后,便屁顛屁...
    關(guān)機(jī)小姐閱讀 549評(píng)論 2 3

友情鏈接更多精彩內(nèi)容