一、基础知识:先前学习建造者模式的时候,总是以这个UML图作为学习基础资料

然后总是要记住四个角色

  • 产品类:一般是一个较为复杂的对象,也就是说创建对象的过程比较复杂,一般会有比较多的代码量。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成。
  • 抽象建造者:引入抽象建造者的目的,是为了将建造的具体过程交与它的子类来实现。这样更容易扩展。一般至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。
  • 建造者:实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品。
  • 导演类:负责调用适当的建造者来组建产品,导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。住四然后总是要记住四个角色

我们可以看到,建造者模式相对工厂方法模式,更加注重产品建造过程,个人认为这才是Builder的核心思想。

二、近日看了一些Builder的例子,再一次觉得设计模式很多时候是一种思想,而不是照搬UML图

例子1.

 public class User {
private final String firstName; // required
private final String lastName; // required
private final int age; // optional
private final String phone; // optional
private final String address; // optional private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
} public String getFirstName() {
return firstName;
} public String getLastName() {
return lastName;
} public int getAge() {
return age;
} public String getPhone() {
return phone;
} public String getAddress() {
return address;
} public static class UserBuilder {
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address; public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
} public UserBuilder age(int age) {
this.age = age;
return this;
} public UserBuilder phone(String phone) {
this.phone = phone;
return this;
} public UserBuilder address(String address) {
this.address = address;
return this;
} public User build() {
return new User(this);
} }
}

当我们试图创建一个user对象的时候

 public User getUser() {
return new
User.UserBuilder('Jhon', 'Doe')
.age(30)
.phone('1234567')
.address('Fake address 1234')
.build();
}

优点如下:

  • User构造方法是私有的,这意味着该类不能在客户端代码里直接实例化。
  • User所有属性都是final类型的,在构造方法里面被赋值。只提供了getter方法。
  • builder类使用流式接口风格,让客户端代码阅读起来更容易(见getUser())。
  • builder类构造方法只接收必须属性,为了确保这些属性在构造方法里赋值,只有这些属性被定义成final类型。

另外还有一个例子:

AlertDialog

 public class AlertDialog extends Dialog implements DialogInterface {

     ...

     protected AlertDialog(Context context, int theme) {
this(context, theme, true);
} AlertDialog(Context context, int theme, boolean createThemeContextWrapper) {
super(context, resolveDialogTheme(context, theme), createThemeContextWrapper); mWindow.alwaysReadCloseOnTouchAttr();
mAlert = new AlertController(getContext(), this, getWindow());
} protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, resolveDialogTheme(context, 0));
mWindow.alwaysReadCloseOnTouchAttr();
setCancelable(cancelable);
setOnCancelListener(cancelListener);
mAlert = new AlertController(context, this, getWindow());
} public static class Builder {
private final AlertController.AlertParams P;
private int mTheme; public Builder(Context context) {
this(context, resolveDialogTheme(context, 0));
} public Builder(Context context, int theme) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, theme)));
mTheme = theme;
} public Builder setMessage(CharSequence message) {
P.mMessage = message;
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);
dialog.setOnDismissListener(P.mOnDismissListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}
...
}
}

我们可以看到:AlertDialog的Build是一个静态内部类。AlertDialog设置的属性会暂时保存在Build类的成员变量P(AlertController.AlertParams)中。同时,我们注意到我们设置的属性(如setMessage()),它都回返回本身的AlertBuild对象,这样我们就可以不停地调用它设置的方法(流式接口风格)。

如果我们想获得这个AlertDialog。我们就需要调用建造者的create()方法,在create()方法里面它就会构造出一个Dialog实例,并且将我们刚才设置的属性全部赋给AlertDialog,最后返回AlertDialog的实例

三、总结

从上面的UserBuilder和AlertDialog的例子,我们可以做一些总结。Builder设计模式的适用点:

1.产品的属性较多

2.产品本身不可变——Build后,不建议修改产品。

3.产品属性中有部分非必须的属性。

以上三点恰好符合“注重产品创建过程”的Builder核心思想。

参考资料:

http://www.importnew.com/11506.html 建造者模式实践

http://my.oschina.net/weiCloudS/blog/392872?fromerr=AIX2qbD2 在Android中探秘建造者模式

Design Pattern ——Builder的更多相关文章

  1. design pattern Builder 生成器设计模式

    其实设计模式可以学习很有趣,你并不需要有这么难啃旱地FOG对我来说,当然,这些都是健康的骨骼啃啃. 在本文中,建造者模式设计一个搞笑的一幕.根据这一模型来学习功夫的方法,哈哈. 基类的第一,设计.那么 ...

  2. 说说设计模式~大话目录(Design Pattern)

    回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...

  3. 设计模式(Design Pattern)系列之.NET专题

    最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...

  4. [转]Design Pattern Interview Questions - Part 4

    Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...

  5. [转]Design Pattern Interview Questions - Part 1

    Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...

  6. C++ Design Pattern: What is a Design Pattern?

    Q: What is a Design Pattern? A: Design Patterns represent solutions to problems what arise when deve ...

  7. Design Pattern in Simple Examples

    Instead of defining what is design pattern lets define what we mean by design and what we mean by pa ...

  8. java设计模式大全 Design pattern samples in Java(最经典最全的资料)

    java设计模式大全 Design pattern samples in Java(最经典最全的资料) 2015年06月19日 13:10:58 阅读数:11100 Design pattern sa ...

  9. [转]Design Pattern Interview Questions - Part 2

    Interpeter , Iterator , Mediator , Memento and Observer design patterns. (I) what is Interpreter pat ...

随机推荐

  1. Testlink接口使用方法-python语言远程调用

    deepin@deepin-pc:~/test$ cat libclienttestlink.py #!/usr/bin/env python3 # -*- coding: utf-8 -*- #! ...

  2. ExtJs5_使用图标字体来美化按钮

    sencha 的例子中,有使用图标字体来美化按钮的例子,这个用起来又方便风格又统一,例如下图: 上面图标字体的使用方法也很简单,只要下载Font Awesome的css和图标文件,放到项目里就可以了. ...

  3. 转:Git_Windows 系统下Git安装图解

    原文地址:http://blog.csdn.net/jiguanghoverli/article/details/7902791 Windows 系统下Git安装图解 简单来说Git是一个免费的.开源 ...

  4. 【Maven实战】传递性依赖的问题

    在上一篇文章中我们已经介绍了依赖性,这次我们再来介绍下传递依赖的问题,首先我们还是在上篇文章基础之上进行编写. 1.上篇文章中已经建立了一个user-core的模块,现在首先再建立一个user-log ...

  5. Delphi 缩放图像代码 - 支持PNG透明通道(利用了Windows的windowscodecs.dll)

    要求Delphi2007或者更高版本, 系统要求至少XP-SP2以上 实际上是利用了Windows的windowscodecs.dll这个文件的功能 在VCL里已经封装为TWICImage类 proc ...

  6. 【HDOJ】1506 Largest Rectangle in a Histogram

    Twitter还是Amazon拿这个题目当过面试题.DP区间求面积. /* 1506 */ #include <cstdio> #include <cstring> #incl ...

  7. Android 各版本信息 (维基百科)

    The following tables show the release dates and key features of all Android operating system updates ...

  8. DLL入门浅析(1)——如何建立DLL

    转载自:http://www.cppblog.com/suiaiguo/archive/2009/07/20/90619.html 初学DLL,结合教程,总结一下自己的所得,希望对DLL初学者们有所帮 ...

  9. HDU_1401——分步双向BFS,八进制位运算压缩,map存放hash

    Problem Description Solitaire is a game played on a chessboard 8x8. The rows and columns of the ches ...

  10. [Java I/O] TextFile 工具类

    一种常见的编程任务是,从一个文件读取内容,修改内容,再把内容写到另一个文件里. Java 要实现读取.写入操作,需要创建多个类才能产生一个 Stream 进行操作. 下面是一个简单的工具类,封装对文件 ...