簡介
當(dāng)我們在構(gòu)建一個復(fù)雜的對象時记餐,想要把對象的構(gòu)建和表現(xiàn)分離開來驮樊,那么就可以使用Builder模式。比如:構(gòu)建一臺汽車片酝,組成汽車的部件有很多囚衔,像輪胎,發(fā)動機(jī)雕沿,座位等练湿。當(dāng)具備所以的零部件后脆霎,我們組裝好汽車船侧。那么汽車能干什么乙墙,有怎樣的表現(xiàn)深滚,顯然旭从,汽車能夠以一定速度行駛漾肮。那么怎么才能讓汽車行駛呢路星?點(diǎn)火->給油->發(fā)動機(jī)輸出動力等等席镀。這個是汽車能夠行駛起來需要做的榴捡。所以在構(gòu)建復(fù)雜對象過程杈女,為了使構(gòu)建和表現(xiàn)過程分離,那么可以使用Builder模式吊圾。使得構(gòu)建過程和表現(xiàn)過程都可以自由擴(kuò)展达椰。
why
為什么構(gòu)建復(fù)雜對象,要用Builder模式呢街夭?我創(chuàng)建一個對象砰碴,然后向里面設(shè)置屬性不也可以嗎?為什么非要多出一個Builder類來實(shí)現(xiàn)板丽,不是多增加代碼嗎呈枉?
這種想法沒有什么不對,但是從代碼的清晰堵和擴(kuò)展性埃碱,維護(hù)性上看猖辫,其實(shí)還是有很大不同的,可能對于不是非常復(fù)雜的對象砚殿,沒有什么感覺啃憎,當(dāng)你構(gòu)建的對象越來越復(fù)雜,你會發(fā)現(xiàn)它的好處似炎。
其實(shí)很大講設(shè)計模式辛萍,都會列出幾條使用場景悯姊,當(dāng)我不太喜歡,規(guī)則是死的贩毕,其實(shí)我們更應(yīng)該從單一職責(zé)悯许,擴(kuò)展性,可維護(hù)性辉阶,解耦合先壕,封閉性,替換難易等來考慮怎么書寫代碼谆甜。
UML
舉例
public class ExtWebAgent {
private WebSettings mWebSettings;
private ExtWebViewClient mWebViewClient;
private ExtWebChromeClient mWebChromeClient;
private ExtWebView mWebView;
private Context mContext;
private IExtJavascriptInterface mJavascriptInterface;
private IExtWebViewProgress mExtWebViewProgress;
private String mJifName;
IExtCallBack mScrollChangeListener;
private ExtWebAgent(Builder builder, boolean isCache) {this(builder);}
public ExtWebAgent(Builder builder) {
mContext = builder.context;
mWebView = builder.webView;
mWebChromeClient = builder.webChromeClient;
mWebViewClient = builder.webViewClient;
mJavascriptInterface = builder.javascriptInterface;
mJifName = builder.jifName;
mWebView.configWebViewClient(mWebViewClient);
mWebView.configWebChromeClient(mWebChromeClient
.addExtWebViewProgress(mExtWebViewProgress)
mWebView.configOnScrollChanged(mScrollChangeListener);
if (null != mJavascriptInterface) {
mWebView.configJavascriptInterface(mJavascriptInterface, mJifName);
mJavascriptInterface.bindWebView(mWebView);
}
mWebView.setDownloadListener(ExtWebDownLoadListener.instance());
mWebSettings = mWebView.getSettings();
}
public static Builder builder(Context context, IExtWebCallback callback) {
return new Builder(context, callback);
}
public static class Builder {
ExtWebViewClient webViewClient;
ExtWebChromeClient webChromeClient;
ExtWebView webView;
Context context;
IExtJavascriptInterface javascriptInterface;
String jifName = "native";
String cacheBuilderId = "";
Builder(Context context, IExtWebCallback callback) {
if (!(context instanceof Activity || context instanceof Application))
throw new IllegalArgumentException("context is not Activity or Application");
this.context = context;
webChromeClient = new ExtWebChromeClient(cacheBuilderId);
javascriptInterface = new ExtJavaScriptInterfaceIml(cacheBuilderId);
webViewClient = new ExtWebViewClient(cacheBuilderId);
}
public Builder setWebViewClient(ExtWebViewClient wvc) {
webViewClient = null == wvc ? webViewClient : wvc;
return this;
}
public Builder setChromeClient(ExtWebChromeClient wcc) {
webChromeClient = null == wcc ? webChromeClient : wcc;
return this;
}
public Builder addJavascriptInterface(IExtJavascriptInterface jif) {
addJavascriptInterface(jif, jifName);
return this;
}
public Builder addJavascriptInterface(IExtJavascriptInterface jif, String jifName) {
this.jifName = TextUtils.isEmpty(jifName) ? this.jifName : jifName;
javascriptInterface = null == jif ? javascriptInterface : jif;
return this;
}
public Builder bindActAndFrag(String key, IExtWebCallback callback) {
if (null == callback) {
throw new IllegalArgumentException("callback is null");
}
ExtWebViewCallbackManager.instance().bindActAndFrag(key, callback);
return this;
}
public Builder setWebView(ExtWebView wv) {
webView = wv;
context = wv.getContext();
return this;
}
public ExtWebAgent build() {
return new ExtWebAgent(this);
}
}
}
源碼中的Builder模式
AlertDialog.Builder就是典型的Builder模式垃僚。這里不貼代碼了,來個UML圖规辱。
AlertDialog.Builder負(fù)責(zé)組裝谆棺,構(gòu)建。AlertDialog持有AlertController對象按摘,Dialog相關(guān)的操作包券,UI的更新都可以通過它來控制纫谅,這樣相當(dāng)于把Dialog的具體表現(xiàn)抽離出來炫贤,AlertDialog繼承于Dialog,里面負(fù)責(zé)一些事件付秕,狀態(tài)等任務(wù)兰珍。
常用的第三方框架
像Retrofit,okhttp等里面都用到的Builder模式询吴,其用法和上面舉例的一樣掠河。這個模式暫時沒有想到其它變種寫法。
自己的一點(diǎn)理解
其實(shí)Builder模式猛计,簡單點(diǎn)描述就是一個具體對象里面包含了一個用于收集構(gòu)建對象所需要的材料唠摹,當(dāng)收集好后,將其組裝起來奉瘤,形成具有一定表現(xiàn)的對象勾拉。至于這個對象怎樣表現(xiàn)出具有的功能,那么就是對象自己實(shí)現(xiàn)了盗温。