[关闭]
@flyouting 2014-07-03T01:13:07.000000Z 字数 5614 阅读 5456

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

Android 设计模式


简述

建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。

此处输入图片的描述

综合网上各类文章的描述,较为通俗的一种是房屋建造的例子:我的目的是要一座房子,可是我不知道怎么盖,也不知道怎么样设计(建几个房间,几个门),于是我需要找一帮民工,他们会基本的工作,即砌墙,装门等,,还得找个设计师,他知道怎么设计,我需要确保民工听设计师的领导,而设计师本身不干活,只是指挥民工,这里砌一堵墙,这里砌一扇门,这样民工开始建设,最后,我可以向民工要房子了。在这个过程中,设计师是什么也没有,除了他在脑子里的设计和命令,所以要房子也是跟民工要。

代码描述

  1. // 产品(Product)角色
  2. // 首先是房子类,主要是需要描述一下房屋属性
  3. public class Room{
  4. private String window;
  5. private String floor;
  6. }
  1. // 建造者(Builder)角色
  2. // 工人接口,定义了各个工人所要进行的工作。负责进行具体部件如窗户,地板的建造。
  3. // 同时因为房子是民工建的,因此建设完成后由他把房子递交回房主
  4. public interface Builder {
  5. public void makeWindow();
  6. public void makeFloor();
  7. public Room getRoom();
  8. }
  1. // 指导者(Director)角色
  2. // 设计师。他知道房子应该怎么设计,但他不会自己去建造,而是指挥工人建造。
  3. public class Designer {
  4. // 指挥民工进行工作
  5. public void order(Builder builder) {
  6. builder.makeWindow();
  7. builder.makeFloor();
  8. }
  9. }
  1. // 具体建造者(Concrete Builder)角色
  2. // 工人, 负责进行具体部件如窗户,地板的建造。
  3. public class Worker implements Builder {
  4. private Room room = new Room();
  5. public void makeWindow() {
  6. room.window =new String("window");
  7. }
  8. public void makeFloor(){
  9. room.floor = new String("floor");
  10. }
  11. // 回交房子给房主
  12. public Room getRoom() {
  13. return room;
  14. }
  15. }
  1. // 我获取房子的流程
  2. public class Client {
  3. public static void main(String[] args) {
  4. Builder worker = new Worker(); //获取工人对象
  5. Designer designer = new Designer(); //获取设计师对象
  6. designer.order(worker); //设计师指挥工人工作
  7. worker.getRoom(); //工人交房
  8. }
  9. }

Android中的体现

在Android中的体现,常见是就是AlertDialog.buider, Notification.builder。简单看下AlertDialog的部分代码:

  1. // AlertDialog
  2. public class AlertDialog extends Dialog implements DialogInterface {
  3. // Controller, 接受Builder成员变量P中的各个参数
  4. private AlertController mAlert;
  5. // 构造函数
  6. protected AlertDialog(Context context, int theme) {
  7. this(context, theme, true);
  8. }
  9. // 4 : 构造AlertDialog
  10. AlertDialog(Context context, int theme, boolean createContextWrapper) {
  11. super(context, resolveDialogTheme(context, theme), createContextWrapper);
  12. mWindow.alwaysReadCloseOnTouchAttr();
  13. mAlert = new AlertController(getContext(), this, getWindow());
  14. }
  15. // 实际上调用的是mAlert的setTitle方法
  16. @Override
  17. public void setTitle(CharSequence title) {
  18. super.setTitle(title);
  19. mAlert.setTitle(title);
  20. }
  21. // 实际上调用的是mAlert的setCustomTitle方法
  22. public void setCustomTitle(View customTitleView) {
  23. mAlert.setCustomTitle(customTitleView);
  24. }
  25. public void setMessage(CharSequence message) {
  26. mAlert.setMessage(message);
  27. }
  28. // AlertDialog其他的代码省略
  29. // ************ Builder为AlertDialog的内部类 *******************
  30. public static class Builder {
  31. // 1 : 存储AlertDialog的各个参数, 例如title, message, icon等.
  32. private final AlertController.AlertParams P;
  33. // 属性省略
  34. /**
  35. * Constructor using a context for this builder and the {@link AlertDialog} it creates.
  36. */
  37. public Builder(Context context) {
  38. this(context, resolveDialogTheme(context, 0));
  39. }
  40. public Builder(Context context, int theme) {
  41. P = new AlertController.AlertParams(new ContextThemeWrapper(
  42. context, resolveDialogTheme(context, theme)));
  43. mTheme = theme;
  44. }
  45. // Builder的其他代码省略 ......
  46. // 2 : 设置各种参数
  47. public Builder setTitle(CharSequence title) {
  48. P.mTitle = title;
  49. return this;
  50. }
  51. public Builder setMessage(CharSequence message) {
  52. P.mMessage = message;
  53. return this;
  54. }
  55. public Builder setIcon(int iconId) {
  56. P.mIconId = iconId;
  57. return this;
  58. }
  59. public Builder setPositiveButton(CharSequence text, final OnClickListener listener) {
  60. P.mPositiveButtonText = text;
  61. P.mPositiveButtonListener = listener;
  62. return this;
  63. }
  64. public Builder setView(View view) {
  65. P.mView = view;
  66. P.mViewSpacingSpecified = false;
  67. return this;
  68. }
  69. // 3 : 构建AlertDialog, 传递参数
  70. public AlertDialog create() {
  71. // 调用new AlertDialog构造对象, 并且将参数传递个体AlertDialog
  72. final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
  73. // 5 : 将P中的参数应用的dialog中的mAlert对象中
  74. P.apply(dialog.mAlert);
  75. dialog.setCancelable(P.mCancelable);
  76. if (P.mCancelable) {
  77. dialog.setCanceledOnTouchOutside(true);
  78. }
  79. dialog.setOnCancelListener(P.mOnCancelListener);
  80. if (P.mOnKeyListener != null) {
  81. dialog.setOnKeyListener(P.mOnKeyListener);
  82. }
  83. return dialog;
  84. }
  85. }
  86. }

可以看到,通过Builder来设置AlertDialog中的title, message, button等参数, 这些参数都存储在类型为AlertController.AlertParams的成员变量P中,AlertController.AlertParams中包含了与之对应的成员变量。在调用Builder类的create函数时才创建AlertDialog, 并且将Builder成员变量P中保存的参数应用到AlertDialog的mAlert对象中,即P.apply(dialog.mAlert)代码段。我们看看apply函数的实现 :

  1. public void apply(AlertController dialog) {
  2. if (mCustomTitleView != null) {
  3. dialog.setCustomTitle(mCustomTitleView);
  4. } else {
  5. if (mTitle != null) {
  6. dialog.setTitle(mTitle);
  7. }
  8. if (mIcon != null) {
  9. dialog.setIcon(mIcon);
  10. }
  11. if (mIconId >= 0) {
  12. dialog.setIcon(mIconId);
  13. }
  14. if (mIconAttrId > 0) {
  15. dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId));
  16. }
  17. }
  18. if (mMessage != null) {
  19. dialog.setMessage(mMessage);
  20. }
  21. if (mPositiveButtonText != null) {
  22. dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText,
  23. mPositiveButtonListener, null);
  24. }
  25. if (mNegativeButtonText != null) {
  26. dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mNegativeButtonText,
  27. mNegativeButtonListener, null);
  28. }
  29. if (mNeutralButtonText != null) {
  30. dialog.setButton(DialogInterface.BUTTON_NEUTRAL, mNeutralButtonText,
  31. mNeutralButtonListener, null);
  32. }
  33. if (mForceInverseBackground) {
  34. dialog.setInverseBackgroundForced(true);
  35. }
  36. // For a list, the client can either supply an array of items or an
  37. // adapter or a cursor
  38. if ((mItems != null) || (mCursor != null) || (mAdapter != null)) {
  39. createListView(dialog);
  40. }
  41. if (mView != null) {
  42. if (mViewSpacingSpecified) {
  43. dialog.setView(mView, mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight,
  44. mViewSpacingBottom);
  45. } else {
  46. dialog.setView(mView);
  47. }
  48. }
  49. }

实际上就是把P中的参数挨个的设置到AlertController中, 也就是AlertDialog中的mAlert对象。从AlertDialog的各个setter方法中我们也可以看到,实际上也都是调用了mAlert对应的setter方法。在这里,Builder同时扮演了上文中提到的builder、ConcreteBuilder、Director的角色,简化了Builder模式的设计。

优点

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注