這是設(shè)計模式系列的第二篇——建造者設(shè)計模式,我希望推送的文章是一個系列的,盡量保持一樣的寫作風(fēng)格,盡量把我理解的闡述清楚,關(guān)于建造者設(shè)計模式主要從以下幾個方面來學(xué)習(xí),具體如下:
概述
建造者設(shè)計模式(Builder Pattern)屬于創(chuàng)建型設(shè)計模式,主要用于創(chuàng)建復(fù)雜的對象,可將復(fù)雜對象的構(gòu)建過程抽象出來,通過不同實現(xiàn)的構(gòu)建者和裝配者最終組裝出不同的對象,可以非常方便的增加不同實現(xiàn)的構(gòu)建者、組裝者而不用修改以前的代碼。
本質(zhì)
建造者設(shè)計模式(Builder Pattern)分離了對象子組件的構(gòu)造過程和組裝過程,實現(xiàn)了構(gòu)建與組裝的解耦,不同的構(gòu)建器相同的組裝順序以及相同的構(gòu)建器不同的組裝順序都可以創(chuàng)建出不同的對象,使得構(gòu)建與組裝充分解耦,進(jìn)而實現(xiàn)構(gòu)建算法與組裝算法的解耦,從而實現(xiàn)更好的復(fù)用。
關(guān)鍵概念
-
構(gòu)建者(Builder):構(gòu)建不同的子組件且返回子組件或者提供獲取復(fù)雜對象的方法,將構(gòu)建過程抽象成接口或抽象類,方便擴(kuò)展具體的不同的構(gòu)建者。
-
組裝者(Dirctor):通過某個具體的構(gòu)建者構(gòu)建相關(guān)的子組件,同時對外提供組成復(fù)雜產(chǎn)品對象的方法。
當(dāng)需要生成復(fù)雜對象時,直接通過某個具體的組裝者獲得想要的具體對象即可,至于組裝過程與構(gòu)建過程使用者不需要關(guān)心,分別由具體的組裝者與具體的構(gòu)建者內(nèi)部完成。當(dāng)然復(fù)雜對象可以理解為具有很多屬性的對象。
具體實現(xiàn)
下面以手機(jī)的組裝過程來說明建造者設(shè)計模式的具體實現(xiàn),產(chǎn)品類如下:
/**
* 產(chǎn)品
* @author jzman
*/
public class Phone {
private Screen screen;
private Camera camera;
private Cpu cpu;
//省略getter、setter、toString 方法
//...
}
//子組件
class Screen{
private String name;
//...
}
//子組件
class Camera{
private String name;
//...
}
//子組件
class Cpu{
private String name;
//...
}
抽象的構(gòu)建者:
/**
* 構(gòu)建者
* @author jzman
*/
public interface PhoneBuilder {
Screen builderScreen();
Camera builderCamera();
Cpu builderCpu();
}
具體的構(gòu)建者:
/**
* 具體的構(gòu)建者
* @author jzman
*/
public class MiPhoneBuilder implements PhoneBuilder{
@Override
public Screen builderScreen() {
System.out.println("構(gòu)建屏幕...");
return new Screen("Mi-screen");
}
@Override
public Camera builderCamera() {
System.out.println("構(gòu)建相機(jī)...");
return new Camera("Mi-camera");
}
@Override
public Cpu builderCpu() {
System.out.println("構(gòu)建屏幕...");
return new Cpu("Mi-cpu");
}
}
抽象的組裝者:
/**
* 抽象的組裝者
* @author jzman
*/
public interface PhoneDirector {
Phone directPhone();
}
具體的構(gòu)建者:
/**
* 具體的組裝者
* @author jzman
*/
public class MiPhoneDirector implements PhoneDirector{
private PhoneBuilder builder;
public MiPhoneDirector(PhoneBuilder builder) {
this.builder = builder;
}
@Override
public Phone directPhone() {
Phone phone = new Phone();
phone.setScreen(builder.builderScreen());
phone.setCamera(builder.builderCamera());
phone.setCpu(builder.builderCpu());
return phone;
}
}
使用者直接通過某個具體的組裝者獲取最終的產(chǎn)品,具體如下:
public class Client {
public static void main(String[] args) {
PhoneBuilder builder = new MiPhoneBuilder();
MiPhoneDirector director = new MiPhoneDirector(builder);
Phone phone = director.directPhone();
System.out.println(phone);
}
}
執(zhí)行結(jié)果如下:
構(gòu)建屏幕...
構(gòu)建相機(jī)...
構(gòu)建屏幕...
Phone [screen=Screen [name=Mi-screen], camera=Camera [name=Mi-camera], cpu=Cpu [name=Mi-cpu]]
最終,使用者通過具體的組裝者 MiPhoneDirector 組裝出一個具有明顯組裝特征的手機(jī),即一個屏幕是 Mi-screen 、相機(jī)是 Mi-camera、CPU 是 Mi-cpu 的手機(jī)。
總結(jié)
建造者設(shè)計模式(Builder Pattern) 一般用于具有共同特性的復(fù)雜對象,其對象本身與構(gòu)建、組裝過程分離,可做到復(fù)雜對象屬性的可配置,當(dāng)然,如果復(fù)雜對象內(nèi)部過于復(fù)雜,勢必會需要創(chuàng)建更多的構(gòu)建者類,使得構(gòu)建過程繁瑣,我覺得開發(fā)中使用建造者設(shè)計模式主要用來做一些封裝,使得代碼寫起來更靈活,如 Picasso、Glide 的 API 就有建造者設(shè)計模式的使用,使得復(fù)雜對象的一些屬性可以做到可配置,非常方便。
可以選擇關(guān)注微信公眾號:jzman-blog 獲取最新更新,一起交流學(xué)習(xí)!