一、建造者模式概述
1、建造者模式介紹
(1)介紹
- 建造者模式(Builder Pattern)又叫生成器模式,是一種對象構建模式,屬於創建型模式。
- 建造者模式可以將複雜對象的建造過程抽象出來(抽象類別),使這個抽象過程的不同實現方法可以構造出不同表現(屬性)的對象。
- 建造者模式使用多個簡單的對象一步一步構建成一個複雜的對象,它允許用戶只通過指定複雜對象的類型和內容就可以構建它們,用戶不需要知道內部的具體構建細節。
(2)優缺點
- 優點:
- 建造者獨立,易擴展。
- 便於控制細節風險。
- 可以使客戶端不必知道產品內部組成的細節。
- 具體的建造者類之間是相互獨立的,這有利於系統的擴展。
- 具體的建造者相互獨立,因此可以對建造的過程逐步細化,而不會對其他模塊產生任何影響。
- 缺點:
- 建造者模式所創建的產品一般具有較多的共同點,其組成部分相似;如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用範圍受到一定的限制。
- 如果產品的內部變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。
(3)使用場景
- 隔離複雜對象的創建和使用,相同的方法,不同執行順序,產生不同事件結果;
- 多個部件都可以裝配到一個對象中,但產生的運行結果不相同;
- 產品類非常複雜或者產品類因爲調用順序不同而產生不同作用;
- 初始化一個對象時,參數過多,或者很多參數具有默認值;
- Builder模式不適合創建差異性很大的產品類;
- 產品內部變化複雜,會導致需要定義很多具體建造者類實現變化,增加項目中類的數量,增加系統的理解難度和運行成本;
- 需要生成的產品對象有複雜的內部結構,這些產品對象具備共性。
(4)注意事項
- 與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。
2、建造者模式的四個角色
(1)四個角色介紹
- Product(產品角色) :一個具體的產品對象。
- Builder(抽象建造者) :創建一個Product對象的各個部件指定的接口。
- ConcreteBuilder(具體建造者):實現接口,構建和裝配各個部件。
- Director(指揮者):構建一個使用Builder接口的對象。它主要是用於創建一個複雜的對象。它主要有兩個作用,一是隔離了客戶與對象的生產過程,二是負責控制產品對象的生產過程。
(2)四個角色原理類圖
二、建造者模式示例
1、建造者模式示例1
比如我們現在需要烹飪白菜,白菜有不同的做法,炒白菜的大概步驟有買菜、洗菜、炒菜,而辣白菜的步驟有買菜、洗菜、醃菜,白菜湯的步驟有買菜、洗菜、煮菜。
(1)首先創建一個類Product代表成品菜,類中包含具體的做菜步驟
public class Product {
private String buyFood; //買菜
private String washFood; //洗菜
private String fireFood; //炒菜
private String saltFood; //醃菜
private String waterFood; //煮菜
/*省略getter/setter方法*/
}
(2)創建一個抽象建造者Builder 類,定義產品的創建方法和返回方法
public abstract class Builder {
/*產品實例*/
protected Product product = new Product();
/*抽象方法*/
public abstract void buildBuyFood();
public abstract void buildWashFood();
public abstract void buildFireFood();
public abstract void buildSaltFood();
public abstract void buildWaterFood();
/*返回方法*/
public Product getProduct(){
return product;
}
}
(3)創建一個具體建造者ConcreteBuilder 類,具體建造者類實現了抽象建造者類的抽象接口,構建和步驟等
public class ConcreteBuilder extends Builder {
@Override
public void buildBuyFood() {
System.out.println("去超市購買白菜");
}
@Override
public void buildWashFood() {
System.out.println("把白菜清洗乾淨");
}
@Override
public void buildFireFood() {
System.out.println("用火炒菜,做炒白菜");
}
@Override
public void buildSaltFood() {
System.out.println("用鹽醃菜,做辣白菜");
}
@Override
public void buildWaterFood() {
System.out.println("用水煮菜,做白菜湯");
}
}
(4)創建一個指揮者類Director 類
public class Director {
private Builder builder;
/*構造方法的方式注入builder對象*/
public Director(Builder builder){
this.builder = builder;
}
/*set方法注入builder對象*/
public void setBuilder(Builder builder) {
this.builder = builder;
}
/*炒白菜*/
public Product constructFire() {
builder.buildBuyFood();
builder.buildWashFood();
builder.buildFireFood();
return builder.getProduct();
}
/*醃白菜*/
public Product constructSalt() {
builder.buildBuyFood();
builder.buildWashFood();
builder.buildSaltFood();
return builder.getProduct();
}
/*白菜湯*/
public Product constructWater() {
builder.buildBuyFood();
builder.buildWashFood();
builder.buildWaterFood();
return builder.getProduct();
}
}
(5)main方法測試類
public class Jzzms {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
/*調用炒白菜*/
System.out.println("--------炒白菜的做法步驟--------");
director.constructFire();
/*調用醃白菜*/
System.out.println("--------醃白菜的做法步驟--------");
director.constructSalt();
/*調用煮白菜*/
System.out.println("--------白菜湯的做法步驟--------");
director.constructWater();
}
}
(6)輸出結果
--------炒白菜的做法步驟--------
去超市購買白菜
把白菜清洗乾淨
用火炒菜,做炒白菜
--------醃白菜的做法步驟--------
去超市購買白菜
把白菜清洗乾淨
用鹽醃菜,做辣白菜
--------白菜湯的做法步驟--------
去超市購買白菜
把白菜清洗乾淨
用水煮菜,做白菜湯
(7)分析
- 從上面的代碼可以得到,用戶只需要指定需要什麼樣的產品(做什麼菜),而不用去管具體的完成步驟和細節;
- 建造製作過程由指揮者來控制,建造細節由一個抽象類來控制,對於實現建造細節的具體類來說,不會遺漏某一個步驟。
- 指揮者針對抽象建造者編程,客戶端只需要知道具體建造者的類型,即可通過指揮者類調用建造者的相關方法,返回一個完整的產品對象。建造者負責控制產品的生成過程,並且隔離了客戶與生產過程。