您的位置:首页 > 移动开发 > Android开发

Android中的设计模式--建造者模式

2016-11-22 10:36 405 查看
转载请注明出处 http://blog.csdn.net/fofu33/article/details/50973172#comments

之前只知道建造者典型例子是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())


使用时我们这样便可以了。当然单独此例还是构造函数传参来的快。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 设计模式