問題:
在某些情況下,一個(gè)對(duì)象的創(chuàng)建過程非常復(fù)雜,涉及多個(gè)步驟,每個(gè)步驟都可能有不同的實(shí)現(xiàn)方式。如果將所有創(chuàng)建邏輯放在一個(gè)類中,會(huì)導(dǎo)致該類變得龐大且難以維護(hù)。此外,如果需要?jiǎng)?chuàng)建不同的變體對(duì)象,就需要在該類中添加更多的邏輯,使得代碼變得混亂。
解決方案:
建造者模式提供了一種將一個(gè)復(fù)雜對(duì)象的構(gòu)建過程與其表示分離的方法。它將對(duì)象的構(gòu)建過程封裝在一個(gè)獨(dú)立的"建造者"類中,由該類負(fù)責(zé)逐步構(gòu)建對(duì)象。這樣,可以根據(jù)需要?jiǎng)?chuàng)建不同的建造者來構(gòu)建不同的對(duì)象變體。通常,建造者模式涉及以下角色:
- 產(chǎn)品(Product):表示正在構(gòu)建的復(fù)雜對(duì)象。建造者模式的目標(biāo)是構(gòu)建這個(gè)產(chǎn)品。
- 抽象建造者(Abstract Builder):定義了構(gòu)建產(chǎn)品的步驟和方法,但沒有具體的實(shí)現(xiàn)。不同的具體建造者可以實(shí)現(xiàn)不同的構(gòu)建步驟,從而創(chuàng)建不同的產(chǎn)品變體。
- 具體建造者(Concrete Builder):實(shí)現(xiàn)了抽象建造者定義的方法,完成了產(chǎn)品的構(gòu)建過程。每個(gè)具體建造者負(fù)責(zé)構(gòu)建特定的產(chǎn)品變體。
- 指導(dǎo)者(Director):負(fù)責(zé)控制建造的過程。它通過將客戶端與具體建造者分離,確保產(chǎn)品的構(gòu)建是按照一定順序和規(guī)則進(jìn)行的。
效果:
建造者模式的效果包括:
- 分離構(gòu)建過程和表示:通過建造者模式,可以將復(fù)雜對(duì)象的構(gòu)建過程與其最終表示分離,使得構(gòu)建過程更加清晰可控。
- 支持不同的表示:通過使用不同的具體建造者,可以創(chuàng)建不同的產(chǎn)品表示,而不改變客戶端的代碼。
- 更好的可擴(kuò)展性:如果需要添加新的產(chǎn)品變體,只需創(chuàng)建一個(gè)新的具體建造者即可,而無需修改已有的代碼。
- 隱藏產(chǎn)品的內(nèi)部結(jié)構(gòu):客戶端只需與抽象建造者和指導(dǎo)者交互,無需關(guān)心產(chǎn)品的內(nèi)部構(gòu)建細(xì)節(jié)。
總之,建造者模式適用于需要構(gòu)建復(fù)雜對(duì)象,且構(gòu)建過程涉及多個(gè)步驟或變體的情況。通過將構(gòu)建過程分解為可重用的步驟,建造者模式提供了一種結(jié)構(gòu)化的方法來創(chuàng)建對(duì)象。
代碼示例:
// 首先,我們定義房屋類 House,它具有多個(gè)屬性,如地基、結(jié)構(gòu)、屋頂和裝修。
class House {
private String foundation;
private String structure;
private String roof;
private String interior;
public void setFoundation(String foundation) {
this.foundation = foundation;
}
public void setStructure(String structure) {
this.structure = structure;
}
public void setRoof(String roof) {
this.roof = roof;
}
public void setInterior(String interior) {
this.interior = interior;
}
@Override
public String toString() {
return "House [foundation=" + foundation + ", structure=" + structure + ", roof=" + roof + ", interior=" + interior + "]";
}
}
// 然后,我們創(chuàng)建一個(gè)抽象建造者類 HouseBuilder,它定義了構(gòu)建房屋的方法。
abstract class HouseBuilder {
protected House house = new House();
public abstract void buildFoundation();
public abstract void buildStructure();
public abstract void buildRoof();
public abstract void buildInterior();
public House getHouse() {
return house;
}
}
// 接下來,我們創(chuàng)建兩個(gè)具體的建造者類 ConcreteHouseBuilder 和 LuxuryHouseBuilder
// 分別實(shí)現(xiàn)了不同類型房屋的構(gòu)建過程。
// 具體建造者類 - 普通房屋
class ConcreteHouseBuilder extends HouseBuilder {
@Override
public void buildFoundation() {
house.setFoundation("Standard Foundation");
}
@Override
public void buildStructure() {
house.setStructure("Standard Structure");
}
@Override
public void buildRoof() {
house.setRoof("Standard Roof");
}
@Override
public void buildInterior() {
house.setInterior("Standard Interior");
}
}
// 具體建造者類 - 豪華房屋
class LuxuryHouseBuilder extends HouseBuilder {
@Override
public void buildFoundation() {
house.setFoundation("Strong Foundation");
}
@Override
public void buildStructure() {
house.setStructure("Reinforced Structure");
}
@Override
public void buildRoof() {
house.setRoof("Elegant Roof");
}
@Override
public void buildInterior() {
house.setInterior("Luxury Interior");
}
}
// 最后,我們創(chuàng)建指導(dǎo)者類 Director,它協(xié)調(diào)建造過程并返回構(gòu)建的房屋對(duì)象。
class Director {
private HouseBuilder builder;
public Director(HouseBuilder builder) {
this.builder = builder;
}
public House constructHouse() {
builder.buildFoundation();
builder.buildStructure();
builder.buildRoof();
builder.buildInterior();
return builder.getHouse();
}
}
// 這個(gè)示例演示了如何使用建造者模式創(chuàng)建不同類型的房屋,每種房屋類型的建造過程都由相應(yīng)的具體建造者類負(fù)責(zé)實(shí)現(xiàn),而指導(dǎo)者類負(fù)責(zé)協(xié)調(diào)建造過程。
public class BuilderPatternExample {
public static void main(String[] args) {
HouseBuilder concreteBuilder = new ConcreteHouseBuilder();
Director director1 = new Director(concreteBuilder);
House concreteHouse = director1.constructHouse();
System.out.println("Concrete House: " + concreteHouse);
HouseBuilder luxuryBuilder = new LuxuryHouseBuilder();
Director director2 = new Director(luxuryBuilder);
House luxuryHouse = director2.constructHouse();
System.out.println("Luxury House: " + luxuryHouse);
}
}