建造者模式的介紹
将一個複雜對象的建構與它的表示分離,使得同樣的過程可以建造不同的表示。該模式屬于建立型模式。本質上該模式就是一個對象的建立不是該類自己進行建立而是通過其他類進行建立。
建造者模式參與角色
參與角色 | 功能 |
---|---|
産品(Product) | 是一個被建構的對象,其建構過程在具體建造者中實作 |
建造者(builder) | 是具體建造者抽象或接口,内部是複雜産品的建構方法,但本身并不實作相關功能 |
具體建造者(ConcreteBuilder) | 實作建造者的的相關功能,用于對産品進行建構,具體化複雜對象各部分的建立 |
指揮者(director) | 指揮建造的具體流程,在内部持有一個建造者的引用,并實作了建造一個産品的流程 |
建造者模式UML
相關案例
在小明的表哥幫助小明組裝好電腦後,小明的兩個同學小紅和小王也想讓他的表哥幫他們組裝電腦,他們把他們組裝的電腦元件都給了小明,他們組裝電腦的配件是不一緻的。下面我們将使用建造者模式來實作這個案例。
案例分析
分析題目我們可以知道需求為獲得兩台組裝好的電腦,我們需要使用建造者模式來實作。
使用建造者模式我們來劃分四個角色
- 産品(product):電腦,我們需要定義一個電腦類,在内部有組裝電腦的各種 方法。
- 建造者(builder):定義一個組裝各個配件的抽象方法。
- 具體建造者:有兩個,一個是建構小紅電腦的建構者,一個是建構小王電腦的建構者;相同點是他們的内部都是實作了建造者類的方法,不同點是組裝電腦的配件不一緻(就是内部細節不一緻)。
- 指揮者(director):表哥,他決定了電腦如何裝配,在這裡我們需要定義一個表哥類,在内部持有一個建造者引用,并且擁有一個決定裝配電腦流程的方法。(注意在指揮者角色中建造的步驟是可以更改,這為程式提供了比較大的靈活性)
在分析完全部角色後我們可以開始具體的設計所需的類以及各個類所需的功能。
将外觀模式和建造者模式進行比較:
(1)功能不一樣,在建造者模式中我們建立的是一個對象,在外觀模式中我們是把多個複雜的子系統的使用進行簡化,合并。
(2)目的不一樣。在建造者模式中我們是想将一個複雜對象的建構和表示分開,這樣當我們對複雜對象進行維護的時候會比較簡單;在外觀模式中我們是希望在複雜的系統環境中将系統的使用變得更為簡單,這樣可以減少類之間的耦合性。
案例實作
産品角色代碼
package builder.pattern;
import java.util.LinkedList;
import java.util.List;
/**
* @Introduction 該類是一個産品角色,内部包含,組裝電腦的方法
*/
public class Product {
private List<String> assemble=new LinkedList<String>();
/**組裝部件,在這裡我們可以在具體構造類中調用該方法來表示裝配了什麼部件*/
public void assemblePart(String name) {
assemble.add(name);
}
/**展示裝配的部件,為了展示效果,在真正的實際中這個不需要*/
public void show() {
for(String s:assemble) {
System.out.println(s);
}
}
}
建造者角色
package builder.pattern;
/**
* @Introduction 該類所扮演的角色是Builder角色内部含有建立一個Product的所有方法,但不實作
*/
public abstract class Builder {
public abstract void assembleCpu(); //裝配Cpu
public abstract void assembleZhuBan(); //裝配主機闆
public abstract void assembleNeiCun(); //裝配記憶體
public abstract Product getResult();
}
具體建造者角色
(1)組裝小紅電腦
package builder.pattern;
/**
* @Introduction 該類所扮演的角色是具體建造者,繼承了Builder抽象類,實作了為小紅建構的電腦的所有需要子產品
*/
public class BuilderXiaoHong extends Builder{
private Product xiaoHong=new Product(); //内部持有一個Product對象
/**實作了建造方法,這裡這是實作了産品的子產品的建構,并未将産品進行組裝,也就是在真正執行的時候我們可以先裝Cpu,然後在裝主機闆
* ;但也可以先裝主機闆,再裝Cpu*/
@Override
public void assembleCpu() {
xiaoHong.assemblePart("為小紅電腦裝Cpu");
}
@Override
public void assembleZhuBan() {
xiaoHong.assemblePart("為小紅電腦裝主機闆");
}
@Override
public void assembleNeiCun() {
xiaoHong.assemblePart("為小紅電腦裝記憶體");
}
/**将建立好的角色傳回(但不是直接傳回,而是在經過指揮者之後再傳回Product*/
@Override
public Product getResult() {
return xiaoHong;
}
}
(2)組裝小王電腦
package builder.pattern;
/**
* @Introduction 該類所扮演的角色是具體建造者,實作了Builder類,用于實作小明電腦組裝的各個具體的步驟,但不進行組裝
*/
public class BuilderXiaoWang extends Builder{
private Product xiaoWang=new Product(); //内部持有一個Product對象
/**實作了建造方法,這裡這是實作了産品的子產品的建構,并未将産品進行組裝,也就是在真正執行的時候我們可以先裝Cpu,然後在裝主機闆
* ;但也可以先裝主機闆,再裝Cpu*/
@Override
public void assembleCpu() {
xiaoWang.assemblePart("為小王紅電腦裝Cpu");
}
@Override
public void assembleZhuBan() {
xiaoWang.assemblePart("為小王紅電腦裝主機闆");
}
@Override
public void assembleNeiCun() {
xiaoWang.assemblePart("為小王紅電腦裝記憶體");
}
/**将建立好的角色傳回(但不是直接傳回,而是在經過指揮者之後再傳回Product*/
@Override
public Product getResult() {
return xiaoWang;
}
}
指揮者角色
package builder.pattern;
/**
* @Introduction 該類扮演的角色是指揮者,作用為将具體建造者中的方法按照使用者定義的規則進行組裝。就如同在做菜是我們需要裝盤、放鹽
* 翻炒菜一樣,在了解我們需要做什麼之後,我們需要了解怎麼去做,做一道菜的順序是什麼,将剛剛的動作按照炒菜的順序去執行。
*
*/
public class BiaoGe {
/**進行指揮,按照一定的順序去執行Builder中對應的操作(第一種組裝順序)*/
public void constructOne(Builder computer) {
computer.assembleCpu(); //先組裝Cpu
computer.assembleNeiCun(); //再組裝記憶體
computer.assembleZhuBan(); //最後組裝主機闆
}
/**第二種組裝順序*/
public void constructTwoOne(Builder computer) {
computer.assembleNeiCun(); //先組裝記憶體
computer.assembleCpu(); //再先組裝Cpu
computer.assembleZhuBan(); //最後組裝主機闆
}
}
使用者界面模拟
package builder.pattern;
/**
1. @Introduction 該類是模拟使用者對相關産品進行建立的過程
2. */
public class UserIn {
public static void main(String[] args) {
Builder builder; //所有具體構造者非一個抽象接口
Product computer;
BiaoGe biaoge=new BiaoGe(); //指揮Builder建構出相應computer
/**組裝小紅的電腦*/
builder=new BuilderXiaoHong(); //實作産品的各個部件的建構
biaoge.constructOne(builder); //将産品的各個部件進行組合執行,産生出一個真正的産品
computer=builder.getResult(); //将建造好的對象執行個體傳回(實作了複雜對象的建構和表示分離)
computer.show();
/**組裝小王的電腦*/
builder=new BuilderXiaoWang();
biaoge.constructOne(builder);
computer=builder.getResult();
computer.show();
}
}
運作結果如下
建造者模式優缺點
優點:
- 提高了系統的可拓展性和可維護性,在建造者模式中将複雜對象的建立和表示進行了分離,同時使用了指揮者提高了複雜對象的靈活性,可以對複雜産品的細節進行較好的控制。
- 實作了細節依賴于抽象,可以是相同的建構過程得到不同産品。
缺點:
如果産品的具體構造者很多,這無疑會使得系統變得更加龐大,提高了系統的複雜度。
建造者模式适用場景
(1)需要建立的對象内部結構比較複雜,需要将對象的建構和表象分離。
(2)需要相同的建構過程可以獲得不同的産品。