加州計劃 2030 年銷售 61% 的電動汽車,環保組織:不行,提高到 80%
阿新 • • 發佈:2022-03-09
在有些情況下,一個物件會有一些重要的性質,在他們沒有被賦值之前,物件不能作為一個完整的產品使用。比如,一個電子郵件有發件人地址、收件人地址、主題、內容、附件等,最起碼在收件人地址沒有賦值之前,這個電子郵件是不能發出的。
在有些情況下,一個物件的一些性質必須按照某個順序賦值才有意義,在某個性質沒有賦值之前,另一個性質則無法賦值。比如,建造房子,一定是要先打地基,然後砌牆,最後封頂。
傳統方式:
這裡我們以建造房屋為例來做說明。首先看傳統方式的建造房屋的方式:
抽象類:
package com.charon.builder; /** * @className: AbstractHouse * @description: 抽象類 * @author: charon * @create: 2022-03-13 16:54 */ public abstract class AbstractHouse { /** * 打地基 */ public abstract void buildBasic(); /** * 砌牆 */ public abstract void buildWalls(); /** * 封頂 */ public abstract void roofed(); /** * 建造房屋的方法 */ public void build(){ buildBasic(); buildWalls(); roofed(); } }
實現類:
package com.charon.builder; /** * @className: CommonHouse * @description: 普通房子建造類 * @author: charon * @create: 2022-03-13 16:57 */ public class CommonHouse extends AbstractHouse { @Override public void buildBasic() { System.out.println("普通房子打地基。。。。。"); } @Override public void buildWalls() { System.out.println("普通房子砌牆。。。。。"); } @Override public void roofed() { System.out.println("普通房子封頂。。。。。"); } }
測試:
package com.charon.builder;
/**
* @className: Client
* @description:
* @author: charon
* @create: 2022-03-13 17:01
*/
public class Client {
public static void main(String[] args) {
CommonHouse commonHouse = new CommonHouse();
commonHouse.build();
}
}
傳統方式的優點是比較好理解,簡單易操作。但缺點是設計的程式結構過於簡單,沒有設計快取層物件,程式的擴充套件和維護不好,也就是說,這種設計方案,把產品(即:房子)和建立產品的過程(即:建房子流程)封裝在一起,耦合性增強。
建造模式:
建造者模式也叫生成器模式,可以將一個產品的內部表象與產品的生成過程分割開來,從而可以是一個建造過程生成具有不同的內部表象的產品物件。建造者模式是一步一步建立一個複雜的物件,他允許使用者只通過指定複雜物件的型別和內容就可以構建他們,使用者不需要知道內部的具體構建細節。
建造模式的UML類圖:
建造者模式主要涉及到抽象建造者、具體建造者、產品、指揮者以下四種角色:
- 抽象建造者:給出一個抽象介面,以規範產品物件的各個組成成分的建造。通常以抽象類或介面的形式出現。
- 具體建造者:擔任這個角色的是與應用程式緊密相關的一些類,他們在應用程式呼叫下建立產品的例項。主要由兩個任務:1)實現抽象建造者所宣告的介面,給出一步一步地完成建立產品例項地操作。2).在建造過程完成後,提供產品的例項
- 產品角色:產品是建造中的複雜物件,一般來說,一個系統中會有對於一個的產品類,而且這些產品類並不一定有共同的介面。
- 指揮者:擔任這個角色的類呼叫具體建造者角色以建立產品物件,應當指出的是,指揮者角色並沒有產品類的具體只是,真正擁有產品類的具體知識的是具體建造者角色。他的作用主要有兩點:1).隔離了客戶與物件的生產過程,2).負責控制產品物件的生產過程。
抽象建造者:
package com.charon.builder.improve;
/**
* @className: HouseBuilder
* @description: 抽象的建造者
* @author: charon
* @create: 2022-03-13 19:15
*/
public abstract class HouseBuilder {
private House house = new House();
/**
* 打地基
*/
public abstract void buildBasic();
/**
* 砌牆
*/
public abstract void buildWalls();
/**
* 封頂
*/
public abstract void roofed();
/**
* 建造方法,將產品返回
* @return
*/
public House buildHouse(){
return house;
}
}
具體建立者:
package com.charon.builder.improve;
/**
* @className: CommonHouse
* @description:
* @author: charon
* @create: 2022-03-13 19:13
*/
public class CommonHouse extends HouseBuilder {
@Override
public void buildBasic() {
System.out.println("普通房子打地基。。。。。");
}
@Override
public void buildWalls() {
System.out.println("普通房子砌牆。。。。。");
}
@Override
public void roofed() {
System.out.println("普通房子封頂。。。。。");
}
}
package com.charon.builder.improve;
/**
* @className: HighBuilding
* @description: 高樓
* @author: charon
* @create: 2022-03-13 19:18
*/
public class HighBuilding extends HouseBuilder{
@Override
public void buildBasic() {
System.out.println("高樓 打地基。。。。。");
}
@Override
public void buildWalls() {
System.out.println("高樓 砌牆。。。。。");
}
@Override
public void roofed() {
System.out.println("高樓 封頂。。。。。");
}
}
產品角色:
package com.charon.builder.improve;
/**
* @className: House
* @description: 產品角色
* @author: charon
* @create: 2022-03-13 19:14
*/
public class House {
/**
* 地基
*/
private String basic;
/**
* 牆
*/
private String walls;
/**
* 封頂
*/
private String roofed;
/**
* Gets the value of basic
*
* @return the value of basic
*/
public String getBasic() {
return basic;
}
/**
* Sets the basic
*
* @param basic basic
*/
public void setBasic(String basic) {
this.basic = basic;
}
/**
* Gets the value of walls
*
* @return the value of walls
*/
public String getWalls() {
return walls;
}
/**
* Sets the walls
*
* @param walls walls
*/
public void setWalls(String walls) {
this.walls = walls;
}
/**
* Gets the value of roofed
*
* @return the value of roofed
*/
public String getRoofed() {
return roofed;
}
/**
* Sets the roofed
*
* @param roofed roofed
*/
public void setRoofed(String roofed) {
this.roofed = roofed;
}
}
指揮者:
package com.charon.builder.improve;
/**
* @className: HouseDirector
* @description: 指揮者
* @author: charon
* @create: 2022-03-13 19:20
*/
public class HouseDirector {
HouseBuilder houseBuilder = null;
public HouseDirector(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
/**
* Sets the houseBuilder
*
* @param houseBuilder houseBuilder
*/
public void setHouseBuilder(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
/**
* 將建造房子的流程交給指揮者
* @return
*/
public House constructHouse(){
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.roofed();
return houseBuilder.buildHouse();
}
}
測試:
package com.charon.builder.improve;
/**
* @className: Client
* @description:
* @author: charon
* @create: 2022-03-13 19:19
*/
public class Client {
public static void main(String[] args) {
// 蓋普通房子
CommonHouse commonHouse = new CommonHouse();
// 準備建立房子的指揮者
HouseDirector houseDirector = new HouseDirector(commonHouse);
// 完成蓋房子
houseDirector.constructHouse();
// 蓋高樓
houseDirector.setHouseBuilder(new HighBuilding());
// 完成蓋房子
houseDirector.constructHouse();
}
}
列印:
普通房子打地基。。。。。
普通房子砌牆。。。。。
普通房子封頂。。。。。
高樓 打地基。。。。。
高樓 砌牆。。。。。
高樓 封頂。。。。。
注意事項和細節:
- 客戶端不必知道產品內部組成的細節,將產品本身與產品的建立過程解耦,是的相同的建立過程可以建立不同的產品物件
- 每一個具體建造者都相對獨立,而與其他的具體建造者無關,因此可以很方便的替換具體建造者或增加新的具體建造者,使用者使用不的具體建造者即可得到不同的產品物件
- 可以更加精細地控制產品地建立過程,將複雜產品地建立步驟分解在不同的方法中,使得創新過程更加清晰,也更方便使用程式來控制建立過程
- 增加新的具體建造者無需修改原有類庫的程式碼,指揮者類針對抽象建造者類程式設計,系統擴充套件方便,符合“開-閉”原則
- 建造者模式所建立的產品一般具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,則不適合使用建造者模式,因為其使用範圍收到一定的限制
- 如果產品的內部變化負責,可能會導致需要定義很多具體建立者類來實現這種變化,導致系統變得很龐大,因此在這種情況下,要考慮是否選擇建立者模式
抽象工廠模式與建立者模式的不同:
抽象工廠模式實現對產品家族的建立,一個產品家族是一系列產品,具有不同分類維度的產品組合,採用抽象工廠模式不需要關心構建過程,只關心什麼產品由什麼工廠生產即可。而建造者模式則是要求按照指定的藍圖建立產品,他的主要目的是通過組裝零配件而生成一個新的產品。