設計模式之構建者Builder模式
在前一段時間因為業務需求,標題欄的樣式變得越來越多的元素增加,導致在TitleBarView(標題欄)的構造方法變得十分的累贅,於是我開始著手優化TitleBarView。
場景分析
public void initBannerView(String title) {
initBannerView(title, mBack, null);
}
public void initBannerView(String title, View.OnClickListener l, View.OnClickListener r) {
initBannerView(title, l, r, 0 );
}
public void initBannerView(String title, View.OnClickListener l, View.OnClickListener r, int rightIcon) {
···
}
這是原本的TitleView的方法,但是新的需求下,需要新增構造方法,TitleBarView將會越來越複雜。首先我們看一下這種採用重疊構造器的不足,引數不多的情況下,是比較方便快捷的,一旦引數多了,程式碼可讀性大大降低,並且難以維護,對呼叫者來說也造成一定困惑;在《Effective Java》中提及到,當遇到多個構造器引數時,我們要考慮選擇用構建器。
Builder模式
Builder模式是不直接生成想要的物件,而是讓客戶端利用所有必要的引數呼叫構造器,得到一個builder物件,然後客戶端在builder物件上呼叫類似setter方法,來設定每一個相關的可選引數,最後客戶端再呼叫無參的builder方法來生成所需的物件。下面就是他的示例:
public class TitleBarView {
private String title;
private OnClickListener leftListener;
private OnClickListener rightListener;
private int rightIcon;
public static final class Builder {
private String title = "預設值標題";
private OnClickListener leftListener = null;
private OnClickListener rightListener = null;
private int rightIcon = -1;
public Builder(String title, OnClickListener leftListener) {
this.title = title;
this.leftListener = leftListener;
}
public Builder rightClickListener(OnClickListener rightListener) {
this.rightListener = rightListener;
return this;
}
public Builder rightIcon(int rightIcon) {
this.rightIcon = rightIcon;
return this;
}
public TitleBarView builder() {
// TODO Auto-generated constructor stub
return new TitleBarView(this);
}
}
private TitleBarView(Builder builder) {
this.title = builder.title;
this.leftListener = builder.leftListener;
this.rightListener = builder.rightListener;
this.rightIcon = builder.rightIcon;
}
}
呼叫方式
new TitleBarView.Builder("Builder模式", null).rightIcon(R.drawable.ic_launcher).builder();
這樣客戶端可以根據需要來對用到的值進行設定。同時在需求變更的時候,可以在TitleBarView類下進行修改,Builder模式採用鏈式呼叫,可讀性和擴充套件性都很好。
Builder模式例子
- Android中的AlertDialog.Builder
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Title");
builder.setMessage("message");
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.setCancelable(false);
builder.show();
- Retrofit2中Retrofit物件的建立
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
從官方的AlertDialog,到現在熱門的第三方開源庫都採用了Builder模式來構建其對應的使用物件,可想而知Builder的確是一個不錯的選擇。在《Effective Java》中的總結是如果類的構造器或者靜態工廠中具有多個引數,設計這種類時,Builder模式就是中不錯的選擇,特別是當大多數引數都是可選的時候,與使用傳統的重疊構造器模式想比,使用Builder模式的客戶端程式碼更易於閱讀和編寫,構建器也比JavaBeans更加安全。
下面我來介紹一下Android Studio的外掛InnerBuilder:
下載外掛:
重啟Android Studio
寫好要準備構建的類的變數:
private String title;
private View.OnClickListener leftListener;
private View.OnClickListener rightListener;
private int rightIcon;
按ALT+SHIFT+S在Generate找到Builder:
選中要使用 Builder 構建的物件,然後勾選使用的配置,點選OK:
程式碼一鍵生成,我就不重複貼程式碼了,大家可以嘗試一下。