建造者設計模式
蓋房項目需求:
1)需要建房子:過程為打地基,砌牆,封頂;(每種房子的建造過程是相同的)
2)房子有各種各樣的,如:普通平房,高樓大廈,别墅,每種房子的建造過程是相同的,但是要求是不同的;
代碼案例一:
//由于所有的房子建造的過程都是相同的,是以可以把房子抽象成一個抽象類;
public abstract class AbstractHourse {
private String baise;
private String wall;
private String roofed;
//打地基
public abstract void builderBasic();
//砌牆
public abstract void builderWalls();
//封頂
public abstract void builderRoofed();
//固定的建造順序
public void builder() {
builderBasic();
builderWalls();
builderRoofed();
}
}
//實作類
public class CommonHouse extends AbstractHourse {
public void builderBasic() {
setBaise("普通房子打地基5m");
System.out.println("普通房子打地基");
}
public void builderWalls() {
setWall("普通房子砌牆10cm");
System.out.println("普通房子砌牆");
}
public void builderRoofed() {
setRoofed("普通房子封頂20cm");
System.out.println("普通房子封頂");
}
}
//測試類
public class Client {
public static void main(String[] args) {
CommonHouse commonHouse = new CommonHouse();
commonHouse.builder();
}
}
優點是結構簡單,易了解
缺點是程式的拓展和維護性不好,這種設計方案,把産品和建立産品的過程封裝在一起,耦合性增強了。
解決方案:将産品和産品的建構過程解耦 =>建造者模式
什麼是建造者設計模式?
建造者設計模式是一個構造複雜對象的設計模式,在一個軟體系統中,可能會面臨建立一個複雜對象的工作,如果使用單一的方法或者單一的對象來建立會比較煩瑣,當所建立複雜對象發生改變時,整個系統就可能面臨劇烈的變化。這時就需要我們将這個複雜對象的建立過程分解成若幹部分,各個子部分用一定的算法構成。但是,子部分可能會經常發生變化,如何能保證整體建立工作的穩定性呢?這就需要建造者模式,建造者模式把複雜對象的建立與表示分離,使得同樣的建構過程可以建立不同的表示。
建造者設計模式的角色
① Product(産品角色):它是包含多個組成部件的複雜對象,由具體建造者來建立其各個零部件。
② builder(抽象建造者):給出一個抽象接口,以規範産品對象的各個組成成分的建造。這個接口規定要實作複雜對象的哪些部分的建立,并不涉及具體的對象部件的建立。通常還包含一個傳回複雜産品的方法 getResult()。
③ ConcreteBuilder(具體建造者):實作Builder接口,針對不同的商業邏輯,具體化複雜對象的各部分的建立。在建造過程完成後,提供産品的執行個體。
④ Director(指揮者):調用具體建造者來建立複雜對象的各個部分,在指揮者中不涉及具體産品的資訊,隻負責保證對象各部分完整建立或按某種順序建立。隔離客戶和對象的生産過程。
代碼案例二:(使用建造者模式解決剛才的蓋房問題)
//房子類(産品類)
public class House {
private String baise;
private String wall;
private String roofed;
}
//抽象的建造者
public abstract class HouseBuilder {
protected House house=new House();
//建造的流程
public abstract void buildBasic();
public abstract void buildWalls();
public abstract void buildRoofed();
//建造房子,房子建造好後将房子傳回
public House buildHouse() {
return house;
}
}
//實際建造者(建造普通房)
public class CommonHouse extends HouseBuilder {
public void buildBasic() {
house.setBaise("普通房子打地基深度5米");
System.out.println("普通房子打地基深度5米");
}
public void buildWalls() {
house.setWall("普通房子砌牆厚度10厘米");
System.out.println("普通房子砌牆厚度10厘米");
}
public void buildRoofed() {
house.setRoofed("普通房子封頂房頂厚度15厘米");
System.out.println("普通房子封頂房頂厚度15厘米");
}
}
//實際建造者(建造高樓大廈)
public class HighBuilding extends HouseBuilder {
public void buildBasic() {
house.setBaise("高樓大廈打地基深度50米");
System.out.println("高樓大廈打地基深度50米");
}
public void buildWalls() {
house.setWall("高樓大廈砌牆厚度20cm");
System.out.println("高樓大廈砌牆厚度20cm");
}
public void buildRoofed() {
house.setRoofed("高樓大廈封頂,玻璃封頂");
System.out.println("高樓大廈封頂,玻璃封頂");
}
}
//指揮者
//指揮者類,指揮者會指揮建造流程,傳回建造好的房子
public class HouseDirector {
HouseBuilder houseBuilder=null;
//通過構造方法傳參的方式初始化建造的房子類型
public HouseDirector(HouseBuilder houseBuilder) {
this.houseBuilder=houseBuilder;
}
//建造不同房子是可通過set修改建造的什麼房子
public void setHouseBuilder(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
//如何處理建造房子的流程由指揮者處理
public House constructHouse() {
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.buildRoofed();
return houseBuilder.buildHouse();
}
}
//使用者類
public class Client {
public static void main(String[] args) {
//蓋普通房子
CommonHouse commonHouse = new CommonHouse();
//建立蓋房的指揮者
HouseDirector houseDirector = new HouseDirector(commonHouse);
//完成蓋房,放回蓋好的房子
House constructHouse = houseDirector.constructHouse();
System.out.println("------------------------");
//蓋高樓大廈
HighBuilding highBuilding = new HighBuilding();
houseDirector.setHouseBuilder(highBuilding);
houseDirector.constructHouse();
}
}
代碼案例三:
//産品
public class Robot {
private String head;//頭
private String hand;//手
private String foot;//腳
private String body;//身體
}
//建造者接口
public interface Builder { //可為抽象類也可以是接口
public abstract void builderHand();
public abstract void builderHead();
public abstract void builderFoot();
public abstract void builderBody();
public abstract Robot createRobot();
}
//接口實作類
public class ATMBuilder implements Builder {
private Robot robot;
public ATMBuilder() {
this.robot = new Robot();
}
@Override
public void builderHand() {
robot.setHand("阿童木的手");
}
@Override
public void builderHead() {
robot.setHead("阿童木的頭");
}
@Override
public void builderFoot() {
robot.setFoot("阿童木的腳");
}
@Override
public void builderBody() {
robot.setBody("阿童木的身體");
}
@Override
public Robot createRobot() {
return robot;
}
}
//指揮者
public class Director {
public Robot createRobotDirector(Builder builder) {
builder.builderFoot();
builder.builderBody();
builder.builderHand();
builder.builderHead();
return builder.createRobot();
}
}
//使用者
public class User {
public static void main(String[] args) {
Director director = new Director();
ATMBuilder atmBuilder = new ATMBuilder();
Robot createRobotDirector2 = director.createRobotDirector(atmBuilder);
System.out.println(createRobotDirector2);
}
}
實用範圍
① 當建立複雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時。
②當構造過程必須允許被構造的對象有不同表示時。
③建立的對象較複雜,由多個部件構成,各部件面臨着複雜的變化,但構件間的建造順序是穩定的。
建造者模式适用于對象結構複雜、對象構造和表示分離的情況。任何一種軟體設計模式的最終目标都是實作軟體的高内聚、低耦合,實作易擴充、易維護。建造者設計模式的實質是解耦組裝過程和建立具體部件,使得不用去關心每個部件是如何組裝的,隻需要知道各個部件是幹什麼的(實作什麼功能)。建造者模式使得産品内部的結構表現可以獨立變化,用戶端不需要知道産品内部結構的組成細節。
建造者模式的注意事項和細節
1)使用者不需要知道産品内部組成的細節,将産品本身與産品的建立過程解耦,使得相同的建立過程可以建立不同的産品對象
2)每個具體建造者都是相對獨立的,而與其他的具體建造者無關,是以可以很友善地替換具體的建造者或者增加新的具體建造者,使用者使用不同的具體建造者就可以得到不同的産品對象
3)可以更加精細地控制産品地建立過程,将複雜産品的建立步驟分解在不同的方法中,使得建立過程更加清晰,也更友善使用程式來控制建立過程。
4)增加新的具體建造者無需修改原有類庫的代碼,指揮者類針對抽象建造者類程式設計,系統擴充友善,符合**“開閉原則”**
建造者設計模式的優點和缺點
**優點:**建造者設計模式的優點在于其建構和表示的分離,有效地将複雜對象處理過程分解,降低功能子產品之間的耦合度,增強子產品内部的内聚度,使得其在軟體設計模式中具有極其重要的位置。
缺點: 1)産品的組成部分必須相同,這限制了其使用範圍
2)如果産品的内部變化複雜,該模式會增加很多的建造者類。