了解了单例模式,接下来介绍另一个常见的模式——Builder模式。

那么什么是Builder模式呢。通过搜索,会发现大部分网上的定义都是

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

但是看完这个定义,依然不知道什么是Builder设计模式。不要过度在意其定义,定义往往是比较抽象的,学习它最好的例子就是通过样例代码。

我们通过一个例子来引出Builder模式。假设有一个Person类,我们通过该Person类来构建一大批人,这个Person类里有很多属性,最常见的比如name,age,weight,height等等,并且我们允许这些值不被设置,也就是允许为null,该类的定义如下。

public class Person {
private String name;
private int age;
private double height;
private double weight; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public double getHeight() {
return height;
} public void setHeight(double height) {
this.height = height;
} public double getWeight() {
return weight;
} public void setWeight(double weight) {
this.weight = weight;
}
}

然后我们为了方便可能会定义一个构造方法。

public Person(String name, int age, double height, double weight) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
}

或许为了方便new对象,你还会定义一个空的构造方法

public Person() {
}

甚至有时候你很懒,只想传部分参数,你还会定义如下类似的构造方法。

public Person(String name) {
this.name = name;
} public Person(String name, int age) {
this.name = name;
this.age = age;
} public Person(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}

于是你就可以这样创建各个需要的对象

Person p1=new Person();
Person p2=new Person("张三");
Person p3=new Person("李四",18);
Person p4=new Person("王五",21,180);
Person p5=new Person("赵六",17,170,65.4);

可以想象一下这样创建的坏处,最直观的就是四个参数的构造函数的最后面的两个参数到底是什么意思,可读性不怎么好,如果不点击看源码,鬼知道哪个是weight哪个是height。还有一个问题就是当有很多参数时,编写这个构造函数就会显得异常麻烦,这时候如果换一个角度,试试Builder模式,你会发现代码的可读性一下子就上去了。

我们给Person增加一个静态内部类Builder类,并修改Person类的构造函数,代码如下。

public class Person {
private String name;
private int age;
private double height;
private double weight; privatePerson(Builder builder) {
this.name=builder.name;
this.age=builder.age;
this.height=builder.height;
this.weight=builder.weight;
}
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public double getHeight() {
return height;
} public void setHeight(double height) {
this.height = height;
} public double getWeight() {
return weight;
} public void setWeight(double weight) {
this.weight = weight;
} static class Builder{
private String name;
private int age;
private double height;
private double weight;
public Builder name(String name){
this.name=name;
return this;
}
public Builder age(int age){
this.age=age;
return this;
}
public Builder height(double height){
this.height=height;
return this;
} public Builder weight(double weight){
this.weight=weight;
return this;
} public Person build(){
return new Person(this);
}
}
}

从上面的代码中我们可以看到,我们在Builder类里定义了一份与Person类一模一样的变量,通过一系列的成员函数进行设置属性值,但是返回值都是this,也就是都是Builder对象,最后提供了一个build函数用于创建Person对象,返回的是Person对象,对应的构造函数在Person类中进行定义,也就是构造函数的入参是Builder对象,然后依次对自己的成员变量进行赋值,对应的值都是Builder对象中的值。此外Builder类中的成员函数返回Builder对象自身的另一个作用就是让它支持链式调用,使代码可读性大大增强。

于是我们就可以这样创建Person类。

Person.Builder builder=new Person.Builder();
Person person=builder
.name("张三")
.age(18)
.height(178.5)
.weight(67.4)
.build();

有没有觉得创建过程一下子就变得那么清晰了。对应的值是什么属性一目了然,可读性大大增强。

其实在Android中, Builder模式也是被大量的运用。比如常见的对话框的创建

AlertDialog.Builder builder=new AlertDialog.Builder(this);
AlertDialog dialog=builder.setTitle("标题")
.setIcon(android.R.drawable.ic_dialog_alert)
.setView(R.layout.myview)
.setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { }
})
.setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { }
})
.create();
dialog.show();

其实在java中有两个常见的类也是Builder模式,那就是StringBuilder和StringBuffer,只不过其实现过程简化了一点罢了。

我们再找找Builder模式在各个框架中的应用。

如Gson中的GsonBuilder,这里只贴出其Builder的使用方法。

GsonBuilder builder=new GsonBuilder();
Gson gson=builder.setPrettyPrinting()
.disableHtmlEscaping()
.generateNonExecutableJson()
.serializeNulls()
.create();

可见各大框架中大量的运用了Builder模式。最后总结一下

  • 定义一个静态内部类Builder,内部的成员变量和外部类一样
  • Builder类通过一系列的方法用于成员变量的赋值,并返回当前对象本身(this)
  • Builder类提供一个build方法或者create方法用于创建对应的外部类,该方法内部调用了外部类的一个私有构造函数,该构造函数的参数就是内部类Builder
  • 外部类提供一个私有构造函数供内部类调用,在该构造函数中完成成员变量的赋值,取值为Builder对象中对应的值

Android开发中常见的设计模式(二)——Builder模式的更多相关文章

  1. Android开发中常见的设计模式 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. Android开发中无处不在的设计模式——动态代理模式

    继续更新设计模式系列.写这个模式的主要原因是近期看到了动态代理的代码. 先来回想一下前5个模式: - Android开发中无处不在的设计模式--单例模式 - Android开发中无处不在的设计模式-- ...

  3. Android开发中常见的设计模式

    对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...

  4. Android开发中常见的设计模式(一)——单例模式

    首先了解一些单例模式的概念. 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 这样做有以下几个优点 对于那些比较耗内存的类,只实例化一次可以大大提高性能,尤其是在移动开发中. 保持 ...

  5. Android开发中常见的设计模式(四)——策略模式

    策略模式定义了一些列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变换. 假设我们要出去旅游,而去旅游出行的方式有很多,有步行,有坐火车,有坐飞机等等 ...

  6. Android开发中常见的设计模式(三)——观察者模式

    先看下这个模式的定义. 定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新 先来讲几个情景. 情景1:有一种短信服务,比如天气预报服务,一旦你订阅 ...

  7. Android开发中常用的设计模式

    首先需要说明的是,这篇博文灵感来自于 http://www.cnblogs.com/qianxudetianxia/archive/2011/07/29/2121547.html ,在这里,博主已经很 ...

  8. Android 开发中常见的注意点

    这里总结了Android开发中常用的注意点.只有总结,没有展开举例讲解,展开的话,一个点都可以写一篇文章了..... 这类问题都一定不要犯. 重要的事情说三遍!!! 说三遍!!! 遍!!! 资源 不允 ...

  9. iOS 开发中常见的设计模式

    最近有小伙伴问到在iOS开发中的几种设计模式,这里摘录一下别人的总结(因为已经感觉总结得差不多了,适用的可以阅读一下) 首先是开发中的23中设计模式分为三大类:1.创建型 2.结构型 3.行为型 (i ...

随机推荐

  1. json server的简单使用(附:使用nodejs快速搭建本地服务器)

    作为前端开发人员,经常需要模拟后台数据,我们称之为mock.通常的方式为自己搭建一个服务器,返回我们想要的数据.json server 作为工具,因为它足够简单,写少量数据,即可使用. 安装 首先需要 ...

  2. 多线程练习,深刻体会了一次变量的BUG.

    package ltb20180106; public class TestBankThread { private int deposit=0;//注意全局变量的摆放. public TestBan ...

  3. 黄聪:C#如何Json转字符串;字符串转Json;Newtonsoft.Json(Json.Net)学习笔记(转)

    Newtonsoft.Json,一款.NET中开源的Json序列化和反序列化类库(下载地址http://json.codeplex.com/). 下面是Json序列化和反序列化的简单封装: /// & ...

  4. Java第02次实验提纲(Java基本语法与类库)

    1. 熟悉Git 1.1 学会使用网页版的操作代码仓库(gitee) 申请账号,然后根据老师提供的链接或者二维码加入团队,然后修改昵称. fork老师提供的代码库项目,新建自己学号命名的文件并上传一些 ...

  5. 关于Maven+Springmvc+Dubbo+Zookeeper整合

    为什么要用dubbo?   还是让官方来解释吧: http://dubbo.io/User+Guide-zh.htm   http://dubbo.io/   一般 nginx+tomcat  | - ...

  6. ALGO-18_蓝桥杯_算法训练_单词接龙(搜索)

    问题描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  7. 学习笔记之NumPy

    NumPy — NumPy http://www.numpy.org/ NumPy is the fundamental package for scientific computing with P ...

  8. docker拉取oracle11g镜像配置

    开始拉取oracle11g镜像 下载过程稍长,镜像大小6.8G(之前拉取过了,所以就不截图了) #docker pull registry.cn-hangzhou.aliyuncs.com/helow ...

  9. 02-第一个Java程序

    学习java的第一个程序 记录自己的学习 记录自己的坚持 记录自己的梦想 public class Hello{ public static void main(String[] args) { Sy ...

  10. 分享微信开发Html5轻游戏中的几个坑

    这段时间团队一直在做微信端的一些产品设计和开发,当然也包含一定的运营工作.做过的东西也不少,微名片.微抢票.微活动.微招聘等一些小case. 今天想说的是我们在微信中被玩的最活跃的轻游戏--微刮奖,这 ...