转载

Android设计模式学习——Builder模式

有的类带有许多设置。可能有点抽象,举例来说:

  1. 一个 Dialog,在创建的时候要设置 Title、Icon、按钮等等。
  2. 一个网络框架(例如 Retrofit)在创建时也需要设置 baseUrl、ConverterFactory、CallAdapterFactory 等等。

如何满足这一需求,我能想出下面这几种方法:

设置一堆构造函数

以 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个构造函数。

设置 setter

还是以 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 模式

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 模式

我们直接来看 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(); 
正文到此结束
Loading...