Java設計模式之建造者模式/生成器模式(Builder)

1. 引入建造者模式

這裏改變了一下思路,先舉一個例子,再總結得出建造者模式的基本結構。

建造者,顧名思義,建造產品的人,什麼產品呢?假設現在建造一個小人。一個小人,要有頭、有身子、有手、有腳。

首先來個人,有屬性:頭、身子、手、腳。

public class Person {
	private String head;
	private String body;
	private String hand;
	private String foot;
	
	public String getHead() {
		return head;
	}
	public void setHead(String head) {
		this.head = head;
	}
	public String getBody() {
		return body;
	}
	public void setBody(String body) {
		this.body = body;
	}
	public String getHand() {
		return hand;
	}
	public void setHand(String hand) {
		this.hand = hand;
	}
	public String getFoot() {
		return foot;
	}
	public void setFoot(String foot) {
		this.foot = foot;
	}
}

好了,下面開始造人,造人就需要造頭、身子、手、腳,這裏定義一個統一標準的抽象類(或接口)。

public abstract class BuildPerson{
	public abstract void buildHead();
	public abstract void buildBody();
	public abstract void buildHand();
	public abstract void buildFoot();
	public abstract Person createPerson();
}

定義好一個造人的標準後,就開始具體的創建過程了。

public class ConcreteBuildPerson extends BuildPerson{
	private Person person = new Person();
	
	@Override
	public void buildHead() {
		person.setHead("造一個頭");
	}

	@Override
	public void buildBody() {
		person.setBody("造一個身體");
	}

	@Override
	public void buildHand() {
		person.setHand("造一雙手");
	}

	@Override
	public void buildFoot() {
		person.setFoot("造一雙腳");
	}

	@Override
	public Person createPerson() {
		System.out.println(person.getHead());
		System.out.println(person.getBody());
		System.out.println(person.getHand());
		System.out.println(person.getFoot());
		return person;
	}

}

其實,這個時候我們已經完成了造人的一個過程,如果只是到這裏,客戶直接調用抽象類去造人,就可以完成造人的需求,但是這樣客戶端就需要造頭、造身體、造手、造腳,耦合性過強,所以在建造者模式中引入了一個很重要的角色——指揮者,由指揮者去完成這些工作。

public class Director {
	public Person constructPerson(BuildPerson builder) {
		builder.buildHead();
		builder.buildBody();
		builder.buildHand();
		builder.buildFoot();
		return builder.createPerson();
	}
}

看,這些工作讓指揮者來做就好了。

public class BuilderTest {

	public static void main(String[] args) {
		Director director = new Director();
		Person person = director.constructPerson(new ConcreteBuildPerson());
	}

}

結果:

這樣一來,客戶只需要說,我想要一個人就可以得到一個人,而無需知道具體的建造過程和細節。

如果客戶說,我想要一個智商180,身高180cm的帥哥,我們只需要增加一個具體實現類(ConcreteBuildPerson2)即可,這就使得具體創建過程和它的表示分離,解了耦。

這樣來看,有負責具體造人的,有負責執行造人過程的,有選擇要什麼類型人的,一塊是一塊,區分得很清楚,這樣也更易於擴展和維護。

2. 建造者模式

2.1 定義

建造者模式,將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。(引入《大話設計模式》)

2.2 結構圖

相關說明:

  • 具體產品(Product):定義具體的產品對象,裏面包含產品的具體屬性。
  • 建造者(Builder):抽象類或抽象接口,是爲了創建Product對象的各個部件指定的一個標準。
  • 具體建造者(ConcreteBuilder):是具體的建造者,繼承或實現Builder,構建和裝配Product的各個部件。
  • 指揮者(Director):根據用戶的需求構建對象。

2.3 基本代碼

Product類——產品類,由多個部件組成。上面例子中的Person類。

/**
 * 產品類
 * 由多個部件組成
 */
public class Product {

	List<String> parts = new ArrayList<String>();
	
	/**
	 * 添加產品部件
	 * @param part
	 */
	public void add(String part) {
		parts.add(part);
	}
	
	/**
	 * 展示所有產品部件
	 */
	public void show() {
		System.out.println("創建產品......");
		for (String part : parts) {
			System.out.println(part);
			
		}
	}
}

Builder類——抽象建造者類,確定產品由哪幾部分組成,這裏假設由兩個部件PartA和PartB組成,並聲明瞭一個得到產品建造後結果的方法getResult,主要是爲了展示該產品包含哪些部件。

/**
 * 抽象建造者類
 */
public abstract class Builder {
	
	public abstract void buildPartA();
	public abstract void buildPartB();
	public abstract Product getResult();
}

ConcreteBuilder1類——具體建造者類,完成具體的建造過程。

/**
 * 具體建造者類
 */
public class ConcreteBuilder1 extends Builder{
	
	private Product product = new Product();

	@Override
	public void buildPartA() {
		product.add("部件P");
	}

	@Override
	public void buildPartB() {
		product.add("部件Q");
	}

	@Override
	public Product getResult() {
		return product;
	}
}

ConcreteBuilder2類——具體建造者類

/**
 * 具體建造者類
 */
public class ConcreteBuilder2 extends Builder{
	
	private Product product = new Product();

	@Override
	public void buildPartA() {
		product.add("部件X");
	}

	@Override
	public void buildPartB() {
		product.add("部件Y");
	}

	@Override
	public Product getResult() {
		return product;
	}
}

Director類——指揮者類,指揮建造過程。

/**
 * 指揮者類
 */
public class Director {

	/**
	 * 指揮建造過程
	 * @param builder
	 */
	public Product construct(Builder builder) {
		builder.buildPartA();
		builder.buildPartB();
		return builder.getResult();
	}
}

客戶端類,客戶不需要知道具體的構建過程和細節。

public class BuilderTest {

	public static void main(String[] args) {
		Director director = new Director();
		Builder builder1 = new ConcreteBuilder1();
		Builder builder2 = new ConcreteBuilder2();
		
		Product product1 = director.construct(builder1);
		product1.show();
		
		Product product2 = director.construct(builder2);
		product2.show();
	}

}

結果:

3. 總結

建造者模式說白了,中心就是要創建東西,那就需要一個東西(Product),需要創建東西的過程(Builder和ConcreteBuilder),執行創建東西過程的人(Director)和吩咐要什麼樣東西的客戶(Client)。

最後說一下,建造者模式的應用場景:

建造者模式是在當創建負責對象的算法應該獨立於該對象的組成部分以及它們的裝配方式時使用的模式。

解釋一下:就是需要客戶和建造過程彼此獨立的情況。

 

寫在最後,

本文主要是小貓看《大話設計模式》的筆記式的記錄,方便以後查閱。

這裏也參考了許多其它博友的博文,再結合自己的理解整理出此文,僅供參考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章