1、概念算法
將一個複雜對像的構建與它的表示分離,使得一樣的構建過程建立不一樣的表示,又叫建造模式。ide
生成器模式的重心在於分離構建算法和具體的構造實現,從而使得構建算法能夠重用。採用不一樣的構建實現,產生不一樣的產品。因此生成器模式都會存在如下兩個部分:ui
a.總體構建算法this
b.部件的構造和產品的裝配spa
2、模式動機3d
生成器模式主要的功能就是構建複雜的產品,且是細化的、分步驟的構建產品,生成器模式重在一步一步解決構造複雜對像的問題。code
3、模式的結構blog
示意代碼:接口
/** * * @ClassName: Product * @Description: TODO(被構建的產品對像接品) * @author beteman6988 * @date 2017年10月1日 上午11:26:33 * */ public interface Product { }
/** * 成生器接口,定義構建一個產品對像所須要的各個部件的操做 * @ClassName: Builder * @author beteman6988 * @date 2017年10月1日 上午11:28:12 * */ public interface Builder { /** * 構建某個部件 * @Title: buildPart * @param * @return void * @throws */ public void buildPart(); /** * 獲取最終生成的產品對像 * @Title: getResult * @param @return * @return Product * @throws */ public Product getResult(); }
public class ConcreteBuilder implements Builder { //最終構建的產品 private Product resultProduct; /** * 獲取最終生成的產品 * @Title: getResult * @param @return * @return Product * @throws */ @Override public Product getResult() { return this.resultProduct; } @Override public void buildPart() { // TODO Auto-generated method stub } }
public class Director { private Builder builder; public Director(Builder builder) { this.builder = builder; } /** * 指導生成器構建最終的產品對像 * @Title: construct * @param * @return void * @throws */ public void construct() { builder.buildPart(); builder.getResult(); } }
a.Builder:生成器接口,定義建立一個Product對像所須要的各個部件的操做。ip
b.ConcreteBuilder:具體生成器的實現,實現各個部件的建立,並負責組裝Product對像的各個部件,同時還提供一個讓用戶獲取組裝完畢後的產品對像的方法。
c.Director:指導者,抽像出來的總體構建算法,主要用來使用Builder,以一個統一的過程來構建所須要的Product對像。
d.Product:產品,表示被生成器構建的複雜對像,包含多個部件。
4、模式樣例
以一次臺式機組裝經歷爲例,當咱們去電腦城組裝電腦時,首先導購小妹妹會拿出一張打印好的空白配置報價單,咱們在導購小妹的引導下,填寫(固然小導購小妹填寫)完了報價單後,而後組裝工程師小哥就會跟據這個報價單,去倉庫領取全部配件,而後就會將全部的配件組裝在一塊兒,一個完整的computer就組裝好了,最後咱們交錢拿電腦走人。
運用生成器模式對上述過程進行分析:
a.Product:導購小妹給咱們的那個報價單能夠說是一臺最終computer product的一個抽像,當咱們填寫完一個一個完整的報價單後,能夠說一個具體的compueter已經有了,
不過目前仍是一堆零部件,要想獲得一臺完整的computer,還須要一個組裝的過程。
b.Builder:咱們的組裝工程師小哥,跟據不一樣的具體報價單,都要去倉庫忙一翻,要找到全部的部件,能夠說只要有報價單,小哥都要將具體產口的每一個部件都要找出來,少一個能夠說都不行,這個能夠說是一個完整電腦每一個部件的抽像的建造(只是去倉庫的相關位置拿到相關部件)。
c.ConcreteBuilder:組裝工程師小哥跟據具體的報價單,去倉庫找到相應的配件,並對每一個部件進行處理,該拆封的拆封,該插線的插線,而後依據必定的步驟組裝將全部配件組裝起來,組裝成一臺完整的電腦。
d.Director:電腦的組裝能夠說有固定的套路,能夠說這個套路適應於全部的電腦組裝,好比必須先有機箱,而後將主板裝到機箱上,而後將cpu裝到主板上,步驟不能亂。按這個套路,工程師小哥跟據不一樣的報價單組裝出不一樣的computer.
代碼以下:
public interface CBuilder { /** * 構建機箱 * @Title: buildBox * @param * @return void * @throws */ public void buildBox(); /** * 安裝主板 * @Title: buildMBoard * @param * @return void * @throws */ public void buildMBoard(); /** * 安裝CPU * @Title: buildCpu * @param * @return void * @throws */ public void buildCpu(); /** * 安裝內存 * @Title: buildMemory * @param * @return void * @throws */ public void buildMemory(); /** * 安裝硬盤 * @Title: buildHDisk * @param * @return void * @throws */ public void buildHDisk(); /** * 返回安裝完畢的計算機 * @Title: getComputer * @param @return * @return ComputerA * @throws */ public ComputerA getComputer(); }
public class ComputerABuilder implements CBuilder {
private ComputerA aComputer=new ComputerA(); @Override public void buildBox() { this.aComputer.setBox("MAtx"); } @Override public void buildMBoard() { this.aComputer.setmBoard("AsusMb"); } @Override public void buildCpu() { this.aComputer.setCpu("Intel CoreI7"); } @Override public void buildMemory() { this.aComputer.setMemory("King stone DDR4"); } @Override public void buildHDisk() { this.aComputer.sethDisk("West Hard Disk 1T"); } @Override public ComputerA getComputer() { // TODO Auto-generated method stub System.out.println("Box:"+this.aComputer.getBox()); System.out.println("MBoard:"+this.aComputer.getmBoard()); System.out.println("Cpu:"+this.aComputer.getCpu()); System.out.println("Memory:"+this.aComputer.getMemory()); System.out.println("HDisk:"+this.aComputer.gethDisk()); return aComputer; } }
public class ComputerA { private String box; private String mBoard; private String cpu; private String memory; private String hDisk; public ComputerA() { super(); } public String getBox() { return box; } public void setBox(String box) { this.box = box; } public String getmBoard() { return mBoard; } public void setmBoard(String mBoard) { this.mBoard = mBoard; } public String getCpu() { return cpu; } public void setCpu(String cpu) { this.cpu = cpu; } public String getMemory() { return memory; } public void setMemory(String memory) { this.memory = memory; } public String gethDisk() { return hDisk; } public void sethDisk(String hDisk) { this.hDisk = hDisk; } }
public class CDirector { private CBuilder theCBuilder; /** * @roseuid 59DB89BE02A1 */ public CDirector(CBuilder builder) { this.theCBuilder=builder; } /** * 獨立出來的構建過程 */ public void construct() { this.theCBuilder.buildBox(); this.theCBuilder.buildMBoard(); this.theCBuilder.buildCpu(); this.theCBuilder.buildMemory(); this.theCBuilder.buildHDisk(); this.theCBuilder.getComputer(); } }
public class Client { public static void main(String[] args) { CBuilder builder=new ComputerABuilder(); CDirector director=new CDirector(builder); director.construct(); } }
運行結果以下:
Box:MAtx
MBoard:AsusMb
Cpu:Intel CoreI7
Memory:King stone DDR4
HDisk:West Hard Disk 1T
5、模式的約束
對於如下狀況應當使用生成器模式:
1.須要生成的產品對像有複雜的內部結構。每一個內部成分能夠是一個對像,也能夠是產品的一個組成部分。
2.須要生產的產品的各個部件之間相互依賴,也就是一個部件的建造必須依賴另外一個部件建造完成才能建造,生成器模式能夠強制實行一種分步驟的建造過程。
3.在對像的建立過程當中會使用到系統中的其它一些對像,這些對像在產品對像的建立過程當中不易獲得。
6、模式的變體與擴展
1.省略抽像生成器Builder角色,若是系統肯定只會有一個具體生成器角色,那麼就能夠省略掉抽像生成器角色,類圖以下:
2.省略指導者角色Director :若是抽像生成器Builder角色被省略,如上面的「1.」的狀況,那麼Director存在的意義就不大了,該角色也能夠進行省略,以下圖:
7、與其它模式的關係
1.生成器模式與工廠方法模式,這兩個模式能夠組合使用。生成器模式的Builder實現中,一般須要選擇具體的部件實現。一個可行的方案就是實現爲工廠方法,一般工廠方法來獲取具體的部件對像,而後再進行部件的裝配。
以下圖:
2.生成器模式與抽像工廠模式,這兩個模式是能夠組合使用的,在生成器模式的Builder實現中,須要建立各個部件對像,而這些部件對像是有關聯的,一般是構成的是一個複雜對像的部件對像。也就是說,Builder實現中,須要獲取構成一個複雜對像的產品族,那天然就可使用抽像工廠模式來實現,這樣一來抽像工廠負責了部件對像的建立,Builder實現裏面則主要負責產品對像的總體構建了。
以下圖:
其實建立模式和抽像工廠模式二者仍是有區別的,抽像工廠模式的主要目的是建立產品族,這個產品族裏面的單個產品就至關因而構成一個複雜對像的部件對像,抽像工廠對像建立完成後就當即返回整個產品族;而生成器的模式的主要目的是按照構造算法,一步一步來構建一個複雜的產品對像,一般要等到整個構建過程結速後,纔會獲得最終的產品對像。
8、模式優缺點
生成器模式能夠用同一個構建算法構建出表現上徹底不一樣的產品,實現產品的構建和產品的表現上的分離。生成器模式正是把產品的構建過程獨立出來,使它和具體產品的表現鬆散耦合,從而使得構建算法能夠重用,而具體產品表現能夠擴展和切換,從產品表現維度很好的支持開閉原則。