生成器模式
建造者模式、Builder
生成器模式 也叫建造者模式,可以理解成可以分步驟創建一個復雜的對象。在該模式中允許你使用相同的創建代碼生成不同類型和形式的對象。
生成器的結構模式
- 生成器(Builder)接口聲明在所有類型生成器中通用的產品構造的步驟
- 具體的生成器(ConcreteBuilders)提供構造過程的不同實現。 具體生成器也可以構造不遵循通用接口的產品。
- 產品 (Products) 是最終生成的對象。 由不同生成器構造的產品無需屬於同一類層次結構或接口。
- 主管 (Director) 類定義調用構造步驟的順序, 這樣你就可以創建和復用特定的產品配置。
- 客戶端 (Client) 必須將某個生成器對象與主管類關聯。 一般情況下, 你只需通過主管類構造函數的參數進行一次性關聯即可。 此后主管類就能使用生成器對象完成后續所有的構造任務。 但在客戶端將生成器對象傳遞給主管類制造方法時還有另一種方式。 在這種情況下, 你在使用主管類生產產品時每次都可以使用不同的生成器。
案例分析
下面我們將結合一輛汽車的制造過程來模擬一個構建構成。針對汽車這種非常復雜的機械結構,我們需要將汽車各個零部件的組裝過程抽取到不同的代碼中,最終組成一個完成的產品。下面我們將簡化這個過程,模擬一輛汽車的車型產品,命名,顏色噴漆,產品定價等信息。
核心類解釋
- 抽象出一個汽車產品
Car
。 - 定義
Builder
接口,規定Car
的構建步驟和過程。 CarBuilder
實現類。CarDirectror
統一構建過程。
代碼實現
Car.class
public class Car {
/**
* 車型 SUV MVP 轎車等
*/
private String type;
/**
* 汽車顏色
*/
private String color;
/**
* 奧迪 啥的
*/
private String name;
/**
* 售價
*/
private BigDecimal price;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"type='" + type + '\'' +
", color='" + color + '\'' +
", name='" + name + '\'' +
", price=" + price +
'}';
}
}
Builder.class
public interface Builder {
/**
* 定義車型
* @param type
* @return
*/
Builder buildType(String type);
/**
* 定義產品名稱
* @param name
* @return
*/
Builder buildName(String name);
/**
* 確定顏色噴漆
* @param color
* @return
*/
Builder buildColor(String color);
/**
* 定價
* @param bigDecimal
* @return
*/
Builder buildPrice(BigDecimal bigDecimal);
/**
* 返回
* @return
*/
Car build();
}
CarBuilder.class
public class CarBuilder implements Builder{
private final Car car = new Car();
@Override
public Builder buildColor(String color) {
car.setColor(color);
return this;
}
@Override
public Builder buildType(String type) {
car.setType(type);
return this;
}
@Override
public Builder buildName(String name) {
car.setName(name);
return this;
}
@Override
public Builder buildPrice(BigDecimal bigDecimal) {
car.setPrice(bigDecimal);
return this;
}
@Override
public Car build() {
return car;
}
}
這里的處理方式只是做解釋,其實還是可以進一步抽象CarBuilder
到具體車型的Builder
,並在次基礎上添加一些驗證的功能
CarDirector.class
public class CarDirector {
public void mpvCarBuilder(Builder builder){
builder.buildName("奧迪");
builder.buildType("mpv");
builder.buildColor("red");
builder.buildPrice(new BigDecimal("400000.00"));
}
public void suvCarBuilder(Builder builder){
builder.buildName("奧迪");
builder.buildType("suv");
builder.buildColor("black");
builder.buildPrice(new BigDecimal("300000.00"));
}
}
Client.class
public class Client {
@Test
public void builderMvp(){
CarDirector carDirector = new CarDirector();
Builder builder = new CarBuilder();
carDirector.mpvCarBuilder(builder);
System.out.println(builder.build().toString());
}
@Test
public void buildSuv(){
CarDirector carDirector = new CarDirector();
Builder builder = new CarBuilder();
carDirector.suvCarBuilder(builder);
System.out.println(builder.build().toString());
}
}
總結
在日常開發中我們能經常用到Builder
設計模式,最常見的就是核心程序中的StringBuilder
了,在開源框架中我們也經常能夠看到,例如Mybatis中的SqlSourceBuilder
、XMLConfigBuilder
等等信息
為了靈活構造復雜對象,該對象會有多個成員變量,在外部調用的時候,不需要或者不方便一次性創建出所有的成員變量,在這種情況下,使用多個構造方法去構建對象,很難維護,這時候Builder設計模式解決這個問題,進行buid()
方法中創建對象,並且將builder
傳入,該builder
中,維護了傳入對象的成員變量。