建造者模式
在用戶不知道對象的建造過程和細節的情況下就可以直接創建複雜的對象
建造者模式適合:
1:複雜對象
2:對象的構建有順序要求,要求先構建part1再構建part2等
先看類圖:
下面舉兩個例子,一個例子就是比較嚴格按照類圖來寫的,另外一個就是更爲通用的對象的建造。
例子1-有指揮者-產品的製作。
這個產品需要先製作 head,才能製作body和tail。
我們先看看產品類,產品類非常簡單,就是普通的JavaBean
/**
* 產品類,這個產品類很奇怪,必須先要頭的信息,然後纔能有body和tail的信息
*/
public class Product {
private String head;//必須先建立頭信息,然後纔有body和tail
private String body;//依賴於頭的信息
private String tail;//依賴頭信息
//getter and setter 略
}
先寫 Build接口:
public interface ProductBuilder {
void buildHead(String head);
void buildBody(String body);
void buildTail(String tail);
Product buildProduct();
}
具體的實現類:
public class RealProductBuilder implements ProductBuilder {
Product product = new Product();
@Override
public void buildHead(String head) {
product.setHead(head);
}
@Override
public void buildBody(String body) {
product.setBody(body);
}
@Override
public void buildTail(String tail) {
product.setTail(tail);
}
@Override
public Product buildProduct() {
return product;
}
}
創建的指揮者
public class ProductDirector {
/**
* 進行構造
* 這個指揮者 是否可以直接 返回Product,
* 然後 就不用再調用build去獲取Product了。可以的
*/
public void construct(ProductBuilder builder,String head,String body,String tail){
System.out.println("先build head信息");
builder.buildHead(head);
System.out.println("再build body");
builder.buildBody(body);
System.out.println("最後build tail");
builder.buildTail(tail);
}
}
測試類:
public static void main(String[] args) {
System.out.println("有指揮者指揮 創建產品");
ProductBuilder builder = new RealProductBuilder();
ProductDirector director = new ProductDirector();
director.construct(builder,"頭信息","身體","尾部");
Product product = builder.buildProduct();
System.out.println(product);
}
測試結果:
有指揮者指揮 創建產品
先build head信息
再build body
最後build tail
Product{head='頭信息', body='身體', tail='尾部'}
可以看到,其實這個結構還是蠻複雜的,爲了實例這個產品,我們引入了一個 builder不算,還額外加了個指揮者 director,而且指揮者 構造產品時,需要傳入的參數也是比較多的,看起來也不是那麼美觀。
山無常形,水無常態。設計模式不是一成不變的一個東西,你感到好用,那就行了。
下面,是一個更爲常見的建造者,它的模式像StringBuilder類似,大家類比即可。
首先我們先看我們的產品:
玩具人類,也是普通的JavaBean
public class Person {
private String legs;
private String hands;
private String head;
private String body;
@Override
public String toString() {
return "Person{" +
"legs='" + legs + '\'' +
", hands='" + hands + '\'' +
", head='" + head + '\'' +
", body='" + body + '\'' +
'}';
}
//getter and setter 略
}
建造者接口:
注意,這裏的每個build返回的都是建造者PersonBuilder本身,也就是我們可以不斷的調用建造方法,時下特別流行的寫法。build.builtA().buildB().buildC();
/**
* 遊戲人物建造類
* 建造身體、頭、腳和手
*/
public interface PersonBuilder {
PersonBuilder buildBody(String body);
PersonBuilder buildHead(String head);
PersonBuilder buildLegs(String legs);
PersonBuilder buildHands(String hands);
/**
* 最後的創建方法
*/
Person build();
}
小肥仔的建造者(具體的建造者):
/**
* 小肥仔
*/
public class FatPersonBuilder implements PersonBuilder {
/**
* 利用組合的方式 把目標對象引入
*/
Person person = new Person();
@Override
public PersonBuilder buildBody(String body) {
person.setBody(body);
return this;
}
@Override
public PersonBuilder buildHead(String head) {
person.setHead(head);
return this;
}
@Override
public PersonBuilder buildLegs(String legs) {
person.setLegs(legs);
return this;
}
@Override
public PersonBuilder buildHands(String hands) {
person.setHands(hands);
return this;
}
@Override
public Person build() {
return person;
}
}
測試方法:
/**
* 無指揮的創建者 類似於 StringBuilder
*/
public class TestNotDirector {
public static void main(String[] args) {
PersonBuilder personBuilder = new FatPersonBuilder();
System.out.println("無指揮的創建者,適合無順序的無檢查的創建對象");
/**
* 創建者 典型的使用方式 .build().build()
*/
Person person = personBuilder.buildBody("強壯的身體")
.buildHands("肥大的手")
.buildLegs("肥大的腿")
.buildHead("聰明的頭")
.build();
System.out.println(person);
}
}
測試結果:
無指揮的創建者,適合無順序的無檢查的創建對象
Person{legs='肥大的腿', hands='肥大的手', head='聰明的頭', body='強壯的身體'}
山無常形,水無常態,設計模式不是死板的東西。