舉個慄子 問題描述 畫一個小人,有頭、身體、兩手、兩腳就可以了。 簡單實現 人類 測試 測試結果 存在問題 畫人的時候,頭身手腳是必不可少的,不管什麼人物,開發時是不能少的。但上面測試代碼中時各部分堆積起來,很容易漏寫,比如導致健全的人物卻少了一條“腿”。而且如果需要在別的地方用這些畫小人的程式怎麼 ...
舉個慄子
問題描述
畫一個小人,有頭、身體、兩手、兩腳就可以了。
簡單實現
人類
/**
* 人類
* Created by callmeDevil on 2019/7/21.
*/
public class Person {
public void drawHead() {
System.out.print("頭 ");
}
public void drawBody() {
System.out.print("身體 ");
}
public void drawHand() {
System.out.print("兩手 ");
}
public void drawLeg() {
System.out.print("兩腳 ");
}
}
測試
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.drawHead();
person.drawBody();
person.drawHand();
person.drawLeg();
}
}
測試結果
頭 身體 兩手 兩腳
存在問題
畫人的時候,頭身手腳是必不可少的,不管什麼人物,開發時是不能少的。但上面測試代碼中時各部分堆積起來,很容易漏寫,比如導致健全的人物卻少了一條“腿”。而且如果需要在別的地方用這些畫小人的程式怎麼辦?
簡單實現2
瘦人類
/**
* 瘦人類
* Created by callmeDevil on 2019/7/21.
*/
public class PersonThinBuilder {
private Person person;
public PersonThinBuilder(Person person){
this.person = person;
System.out.println("瘦人類:");
}
// 建造瘦子
public void build(){
person.drawHead();
person.drawBody();
person.drawHand();
person.drawLeg();
}
}
胖人類
/**
* 胖人類
* Created by callmeDevil on 2019/7/21.
*/
public class PersonFatBuilder {
// 代碼與瘦人類類似
}
測試
public class Test2 {
public static void main(String[] args) {
Person person = new Person();
PersonThinBuilder thin = new PersonThinBuilder(person);
thin.build();
System.out.println();
PersonFatBuilder fat = new PersonFatBuilder(person);
fat.build();
}
}
測試結果
瘦人類:
頭 身體 兩手 兩腳
胖人類:
頭 身體 兩手 兩腳
存在問題
這樣寫的確達到了可以復用這兩個畫小人的目的,但容易“缺胳膊少腿”的問題,依然沒有解決,比如現在需要加一個高個的小人,同樣會因為編程不註意,產生同樣問題。
建造者模式
定義
將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。 如果使用建造者模式,那麼用戶就只需指定需要建造的類型就可以得到它們,而具體建造的過程和細節就不需要知道了。
UML圖
代碼實現
建造人抽象類
/**
* 建造人抽象類
* Created by callmeDevil on 2019/7/21.
*/
public abstract class PersonBuilder {
protected Person person;
public PersonBuilder(Person person){
this.person = person;
}
public abstract void buildHead();
public abstract void buildBody();
public abstract void buildArmLeft();
public abstract void buildArmRight();
public abstract void buildLegLeft();
public abstract void buildLegRight();
}
瘦人類2
/**
* 瘦人類2
* Created by callmeDevil on 2019/7/21.
*/
public class PersonThinBuilder extends PersonBuilder {
public PersonThinBuilder(Person person){
super(person);
}
@Override
public void buildHead() {
System.out.print("頭 ");
}
@Override
public void buildBody() {
System.out.print("身體 ");
}
@Override
public void buildArmLeft() {
System.out.print("左手 ");
}
@Override
public void buildArmRight() {
System.out.print("右手 ");
}
@Override
public void buildLegLeft() {
System.out.print("左腳 ");
}
@Override
public void buildLegRight() {
System.out.print("右腳 ");
}
}
胖人類2
/**
* 胖人類2
* Created by callmeDevil on 2019/7/21.
*/
public class PersonFatBuilder extends PersonBuilder{
// 代碼與瘦人類2類似
}
建造人指揮者
/**
* 建造人指揮者
* Created by callmeDevil on 2019/7/21.
*/
public class PersonDirector {
private PersonBuilder builder;
public PersonDirector(PersonBuilder builder){
// 用戶告訴指揮者需要什麼樣的小人
this.builder = builder;
}
// 根據用戶的選擇建造小人
public void createPerson(){
builder.buildHead();
builder.buildBody();
builder.buildArmLeft();
builder.buildArmRight();
builder.buildLegLeft();
builder.buildLegRight();
}
}
測試
public class Test {
public static void main(String[] args) {
Person person = new Person();
PersonDirector thinDirector = new PersonDirector(new PersonThinBuilder(person));
thinDirector.createPerson();
System.out.println();
PersonDirector fatDirector = new PersonDirector(new PersonFatBuilder(person));
fatDirector.createPerson();
}
}
測試結果
瘦人類2:
頭 身體 左手 右手 左腳 右腳
胖人類2:
頭 身體 左手 右手 左腳 右腳
此時如果需要增加一個高個子和矮個子的小人,應該怎麼做?
加兩個類,一個高個子類和一個矮個子類,都繼承 PersonBuilder ,然後客戶端調用即可。
總結
- 主要是用於創建一些複雜的對象,這些對象內部構建間的建造順序通常是穩定的,但對象內部的構建通常面臨著複雜的變化
- 建造者模式的好處就是使得建造代碼與表示代碼分離,由於建造者隱藏了該產品是如何組裝的,所以若需要改變一個產品的內部表示,只需要再定義一個具體的建造者就可以了
- 建造者模式是在當創建複雜對象的演算法應該獨立於該對象的組成部分以及它們的裝配方式時適用的模式。