有的类带有许多设置。可能有点抽象,举例来说:
如何满足这一需求,我能想出下面这几种方法:
以 Dialog 为例,我可以来一堆:
public Dialog(Context context) {...} public Dialog(Context context, String title) {...} public Dialog(Context context, String message) {...} public Dialog(Context context, String message, Button positiveButton) {...} ...
publicDialog(Contextcontext){...} publicDialog(Contextcontext,Stringtitle){...} publicDialog(Contextcontext,Stringmessage){...} publicDialog(Contextcontext,Stringmessage,ButtonpositiveButton){...} ...
写了四个我就写不动了,为什么?太麻烦了。用排列组合一算,如果有3个可选项,我就得写8个构造函数。
还是以 Dialog 为例,我给出一个最简单的构造函数,然后每个可选项都给一个 setter:
public Dialog(Context context) {//各选项都设个默认值} public void setTitle(String t) {...} public void setIcon(int res) {...} public void setMessage(String m) {...} public void setPositiveButton(Button b) {...} ...
publicDialog(Contextcontext){//各选项都设个默认值} publicvoidsetTitle(Stringt){...} publicvoidsetIcon(intres){...} publicvoidsetMessage(Stringm){...} publicvoidsetPositiveButton(Buttonb){...} ...
这样在创建对象的时候,需要什么就给什么,没给的都采用默认值:
Dialog d = new Dialog(this); d.setTitle("Maxiee"); d.setMessage("http://judymax.com"); d.show();
Dialogd=newDialog(this); d.setTitle("Maxiee"); d.setMessage("http://judymax.com"); d.show();
这个看起来挺好的了,但是还能否更 简洁 一些呢? 那就是实用 Builder 模式 。
在上一节的基础之上,在 Dialog 中添加一个内部类 Builder:
public Dialog(Context context) {//各选项都设个默认值} public void setTitle(String t) {...} public void setIcon(int res) {...} public void setMessage(String m) {...} public void setPositiveButton(Button b) {...} ... // 本节新添加 public class Builder { private Dialog mDialog; public Builder(Context context) { mDialog = new Dialog(context); } public Builder setTitle(String t) { mDialog.setTitle(t); return this; } public Builder setMessage(String m) { mDialog.setMessage(String m); return this; } ... public Dialog create() { return mDialog;} }
publicDialog(Contextcontext){//各选项都设个默认值} publicvoidsetTitle(Stringt){...} publicvoidsetIcon(intres){...} publicvoidsetMessage(Stringm){...} publicvoidsetPositiveButton(Buttonb){...} ... // 本节新添加 publicclassBuilder{ privateDialogmDialog; publicBuilder(Contextcontext){ mDialog=newDialog(context); } publicBuildersetTitle(Stringt){ mDialog.setTitle(t); returnthis; } publicBuildersetMessage(Stringm){ mDialog.setMessage(Stringm); returnthis; } ... publicDialogcreate(){returnmDialog;} }
这样,在使用的时候就可以很帅气地:
new Dialog.Builder(this) .setTitle("Maxiee") .setMessage("http://judymax.com") .create() .show()
newDialog.Builder(this) .setTitle("Maxiee") .setMessage("http://judymax.com") .create() .show()
这样就形成了一个 链式调用 ,一气呵成。
我想的这些思路是否正确呢?来看看 Android 中的 AlertDialog 是如何处理的。
我们直接来看 AlertDialog 的内部类 Builder。
第一个不同是,Builder 有一个成员:
private final AlertController.AlertParams P;
privatefinalAlertController.AlertParamsP;
它是专门用来存放 build 过程中设置的参数的。上一节中,我们在 builder 的构造函数中直接创建 Dialog,然后链式调用 setter 对 Dialog 进行设置。在这里,builder 的构造函数中创建的是一个保存参数的的示例,链式调用 setter 是对这个参数赋值,到最后 create 的时候才创建 AlertDialog 实例:
public AlertDialog create() { final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false); // 用参数设置 Dialog P.apply(dialog.mAlert); ... }
publicAlertDialogcreate(){ finalAlertDialogdialog=newAlertDialog(P.mContext,mTheme,false); // 用参数设置 Dialog P.apply(dialog.mAlert); ... }
AlertDialog 的 builder 里面也是一堆 setter,其内容就是向 P 这个参数成员赋值。实现都大致相同,随便拿出一个看看:
public Builder setPositiveButton(int textId, final OnClickListener listener) { P.mPositiveButtonText = P.mContext.getText(textId); P.mPositiveButtonListener = listener; return this; }
publicBuildersetPositiveButton(inttextId,finalOnClickListenerlistener){ P.mPositiveButtonText=P.mContext.getText(textId); P.mPositiveButtonListener=listener; returnthis; }
最后有一点我发现,AlertDialog 自己又一个 show() 方法(继承自 Dialog 类),AlertDialog 的 Builder 类也有一个 show() 方法。
首先,链式调用最后的那个 show() 调用的是哪个?是 AlertDialog 的。因为 create() 方法返回的类型是 AlertDialog。
那么问题就来了,Builder 里面这个 show() 是干什么用的?看看它的实现:
public AlertDialog show() { AlertDialog dialog = create(); dialog.show(); return dialog; }
publicAlertDialogshow(){ AlertDialogdialog=create(); dialog.show(); returndialog; }
它原来是把 create().show() 这一段给封装了,这一段可以简化为一个 show() :joy::
new AlertDialog.Builder(this) .setA(...) .setB(...) .show();
newAlertDialog.Builder(this) .setA(...) .setB(...) .show();