【设计模式】- Builder(构建者)模式
简介
当我们在构建一个复杂的对象时,想要把对象的构建和表现分离开来,那么就可以使用Builder模式。比如:构建一台汽车,组成汽车的部件有很多,像轮胎,发动机,座位等。当具备所以的零部件后,我们组装好汽车。那么汽车能干什么,有怎样的表现,显然,汽车能够以一定速度行驶。那么怎么才能让汽车行驶呢?点火->给油->发动机输出动力等等。这个是汽车能够行驶起来需要做的。所以在构建复杂对象过程,为了使构建和表现过程分离,那么可以使用Builder模式。使得构建过程和表现过程都可以自由扩展。
why
为什么构建复杂对象,要用Builder模式呢?我创建一个对象,然后向里面设置属性不也可以吗?为什么非要多出一个Builder类来实现,不是多增加代码吗?
这种想法没有什么不对,但是从代码的清晰堵和扩展性,维护性上看,其实还是有很大不同的,可能对于不是非常复杂的对象,没有什么感觉,当你构建的对象越来越复杂,你会发现它的好处。
其实很大讲设计模式,都会列出几条使用场景,当我不太喜欢,规则是死的,其实我们更应该从单一职责,扩展性,可维护性,解耦合,封闭性,替换难易等来考虑怎么书写代码。
UML
Builder模式.png举例
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图。
Builder模式 - AlertDialog.png
AlertDialog.Builder负责组装,构建。AlertDialog持有AlertController对象,Dialog相关的操作,UI的更新都可以通过它来控制,这样相当于把Dialog的具体表现抽离出来,AlertDialog继承于Dialog,里面负责一些事件,状态等任务。
常用的第三方框架
像Retrofit,okhttp等里面都用到的Builder模式,其用法和上面举例的一样。这个模式暂时没有想到其它变种写法。
自己的一点理解
其实Builder模式,简单点描述就是一个具体对象里面包含了一个用于收集构建对象所需要的材料,当收集好后,将其组装起来,形成具有一定表现的对象。至于这个对象怎样表现出具有的功能,那么就是对象自己实现了。