轉載請注明出處!!!http://blog.csdn.net/zhonghuan1992
所有配套代碼均在github上:https://github.com/ZHONGHuanGit/DesignPattern
跟着ZHONGHuan學習設計模式
建造者模式(生成器模式)
簡介:
建造者模式也叫做生成器模式,定義為:封裝一個産品的構造過程,并且按此步驟構造。
建造者模式(生成器模式)屬于建立類模式,和工廠模式相比,你會覺得有點類似,但是有差別之處。不過,建議在看下去之前,得明白三個工廠模式,如果你記得不太清楚了,可以看這裡,簡單工廠,工廠方法,抽象工廠。
UML類圖:
看一下uml類圖。這一部分,如果不清楚,可以先看下面的場景部分,再回過頭來看。
從上面的類圖中,可以看到有四個要素。
1 AbstractBuilder(抽象建造者):引入抽象建造者的目的,是為了将建造的具體過程交與它的子類來實作。這樣更容易擴充。一般會有兩部分抽象方法,一部分用來建造産品,一個是用來傳回産品。如上面,buildPart1和buildPart2用來構造産品,retrieveResult傳回産品。
2 ConcreteBuilder(具體建造者):實作抽象建造者的抽象方法,之是以這樣,是為了便于不同情況下的擴充。
3 Director(導演者):負責調用适當的建造者來組建産品,導演類一般不與産品類發生依賴關系,與導演類直接互動的是建造者類。一般來說,導演類被用來封裝程式中易變的部分。
4 Product(産品類):一般是一個較為複雜的對象,也就是說建立對象的過程比較複雜,一般會有比較多的代碼量。在本類圖中,産品類是一個具體的類,而非抽象類。實際程式設計中,産品類可以是由一個抽象類與它的不同實作組成,也可以是由多個抽象類與他們的實作組成。
場景導入:
假設有這樣的要求,去遊樂場玩,遊樂場有很多可以供娛樂的地方。比如有旋轉木馬,過山車,摩天輪,海盜船等等。當我們去玩得時候,至少不會胡來,自己還是有點計劃的對吧。比如,小明想先去玩過山車(比較喜歡刺激的人),接着摩天輪,然後海盜船,最後旋轉木馬;另外一個小朋友也去玩,他想先玩摩天輪,接着。。。。,等等。假設每個人的計劃就是我們需要的産品,那麼,如果你用工廠模式,如何去設計把這個産品生成出來呢,當然,你一定可以想一些方法,即使不合适,但也可行。這裡,比較合适的方法應該是生成器模式。
重新定義場景:暫時定遊樂場一共有3個活動,分别是,摩天輪,海盜船,過山車。現在我們的産品是要出一份計劃,是先玩哪個,全部玩,還是隻玩一個,這個計劃就是産品。
讓我們看一下實作的代碼:
import java.util.ArrayList;
//假設産品是一份計劃
class Plan{
public ArrayList<String> list = new ArrayList<String>();
void add(String str){
list.add(str);
System.out.println("将\""+str+"\"加入計劃");
}
void Out(){//列印出計劃的内容
System.out.println("計劃内容如下:");
for(String tmp:list){
System.out.println(tmp);
}
}
}
interface AbstractBuilder{
void addRollerCoaster();//将過山車加入計劃
void addFerrisWheel();//将摩天輪加入計劃
void addPirateShip();//将海盜船加入計劃
Plan retrievePlan();//傳回計劃
}
class ConcreteBuilder implements AbstractBuilder{
Plan plan = new Plan();
public void addRollerCoaster(){//将過山車加入計劃
plan.add("roller coaster");
}
public void addFerrisWheel(){//将摩天輪加入計劃
plan.add("ferris wheel");
}
public void addPirateShip(){//将海盜船加入計劃
plan.add("pirate ship");
}
public Plan retrievePlan()//傳回計劃
{
return plan;
}
}
class Director{
public void construct(){
AbstractBuilder builder=new ConcreteBuilder();
builder.addRollerCoaster();
builder.addFerrisWheel();
builder.addPirateShip();
builder.addRollerCoaster();//玩第二次
//建構完畢後,我們就得到了我們的計劃
Plan plan=builder.retrievePlan();
plan.Out();//列印出計劃的内容
}
}
public class Main{
public static void main(String[] args){
Director dir=new Director();
dir.construct();
}
}
輸出:
現在有一個小朋友,他指向玩一個摩天輪,那麼根據他的要求,改變的隻是Director的部分。更改代碼吐下:
class Director{
public void construct(){
AbstractBuilder builder=new ConcreteBuilder();
builder.addFerrisWheel();
//建構完畢後,我們就得到了我們的計劃
Plan plan=builder.retrievePlan();
plan.Out();//列印出計劃的内容
}
}
假設有一個小朋友,計劃玩兩次過山車(刺激男孩),那麼,依舊隻需更改Director的部分。
class Director{
publicvoid construct(){
AbstractBuilder builder=new ConcreteBuilder();
builder.addRollerCoaster();
builder.addFerrisWheel();
builder.addPirateShip();
builder.addRollerCoaster();//玩第二次
//建構完畢後,我們就得到了我們的計劃
Plan plan=builder.retrievePlan();
plan.Out();//列印出計劃的内容
}
}
建造者模式的優點,從上面我們可以體會出一點,product和builder部分一般不變,但是當有新的要求,Director部分可以通過變更滿足這些要求。這種将業務邏輯封裝在導演類(Director)中的方式,對整體而言會有更好的穩定性。
簡單論述工廠與建造者(生成器)模式的差別:
工廠主要變更的地方是産品的變更,而builder 模式主要變更的地方則是director,就是組裝的變更。工廠更傾向基本元件的生産,而builder是這些基本元件的組裝。個人覺得這兩個是可以結合起來的。工廠更基本,builder更高層。