Android中的設計模式--建造者模式
阿新 • • 發佈:2019-01-06
之前只知道建造者典型例子是AlertDialog,它的基本寫法是
public class AlertDialog extends Dialog implements DialogInterface {
private AlertController mAlert;
protected AlertDialog(Context context) {
this(context, resolveDialogTheme(context, 0), true);
}
@Override
public void setTitle(CharSequence title) {
super .setTitle(title);
mAlert.setTitle(title);
}
public void setMessage(CharSequence message) {
mAlert.setMessage(message);
}
public static class Builder {
private final AlertController.AlertParams P;
private int mTheme;
public Builder(Context context, int theme) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, theme)));
mTheme = theme;
}
public Builder setTitle(int titleId) {
P.mTitle = P.mContext.getText(titleId);
return this;
}
public Builder setMessage(CharSequence message) {
P.mMessage = message;
return this;
}
public Builder setOnCancelListener(OnCancelListener onCancelListener) {
P.mOnCancelListener = onCancelListener;
return this;
}
public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
...
return dialog;
}
public AlertDialog show() {
AlertDialog dialog = create();
dialog.show();
return dialog;
}
}
}
簡單說就是把自個兒建構函式變成了保護型別,就不能主動建立了。那麼建立需要一個使用它內部類Builder,給他傳遞AlertDialog標題、提示、點選監聽等進行設定,然後每個函式都返回Builder好持續設定。設定完create構建AlertDialog並賦予對應設定項。
我納悶為什麼不直接new,非要搞個Builder建立,基本程式碼是需要寫兩遍。
昨兩天寫了一個實現TextWatcher 的MyTextWatcher,編輯框emoji表情限制,或者輸入字數限制。但編輯框需求不同,有的是需要限制表情,有的只是需要限制字數回撥剩餘字數,那麼建構函式就如下
public class MyTextWatcher implements TextWatcher {
private EditText editText;
private WatcherListener watcherListener;
private int max_length; //最大輸入字數
private boolean forbiddeEmoji; //是否禁止輸入表情
//普通輸入框watcher
public MyTextWatcher(EditText editText){
super();
this.editText = editText;
}
//限制表情,但無需剩餘字數監聽回撥
public MyTextWatcher(EditText editText, int max_length){
this(editText, max_length, null);
}
/**
* 輸入法監聽工具類建構函式
* @param editText 所需要監聽的editText
* @param max_length editText限制輸入長度
* @param watcherListener 剩餘字數監聽回撥
*/
public MyTextWatcher(EditText editText, int max_length, WatcherListener watcherListener){
this(editText, false, max_length, null);
}
/**
* 輸入法監聽工具類建構函式
* @param editText 所需要監聽的editText
* @param forbiddeEmoji 是否禁止輸入表情
* @param max_length editText限制輸入長度
* @param watcherListener
*/
public MyTextWatcher(EditText editText, boolean forbiddeEmoji, int max_length, WatcherListener watcherListener){
super();
this.forbiddeEmoji = forbiddeEmoji;
this.editText = editText;
this.max_length = max_length;
this.watcherListener = watcherListener;
}
。。。
}
雖然最後一個建構函式已經可以包含前面的建構函式,但呼叫不免不想傳過多的無用引數,所以還是寫了前面的引數少的建構函式。
如果引數更多,需要控制的可能性更多的情況時,你會發現需要寫很多的建構函式去包含這些傳參情況,此時你會發現Builder就能很好的解決這個問題。把所有的需求一次性提完,然後再構建。於是便有了下面的程式碼
public class MyTextWatcher implements TextWatcher {
protected EditText editText;
protected int max_length = -1; //最大輸入字數
protected boolean forbiddeEmoji; //是否禁止輸入表情
protected WatcherListener watcherListener;
protected MyTextWatcher(){
super();
}
...
public interface WatcherListener{
void editTextRemainNum(int num);
}
public static class Builder{
private MyTextWatcher watcher;
public Builder(EditText edit){
watcher = new MyTextWatcher();
watcher.editText = edit;
}
public Builder setMax_length(int max_length) {
watcher.max_length = max_length;
return this;
}
public Builder setForbiddeEmoji(boolean forbiddeEmoji) {
watcher.forbiddeEmoji = forbiddeEmoji;
return this;
}
public Builder setWatcherListener(WatcherListener Listener){
watcher.watcherListener = Listener;
return this;
}
public MyTextWatcher create(){
return watcher;
}
}
}
MyTextWatcher是proctected所以外部無法直接建立,Builder建構函式寫上了MyTextWatcher必須的設定的editText。雖然Builder早有MyTextWatcher成員,但一直藏著噎著只有create()的時候才吐出來。當然MyTextWatcher類中對watcherListener的回撥前需要判空。
tvbrief.addTextChangedListener(new MyTextWatcher.Builder(tvbrief).setForbiddeEmoji(true).setMax_length(MAX_LENGTH).create())
使用時我們這樣便可以了。當然單獨此例還是建構函式傳參來的快。