Java设计中的Builder模式的介绍


Posted in Javascript onMarch 22, 2018

概述

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

使用场景

  • 相同的方法,不同的执行顺序,产生不同的事件结果
  • 多个部件或零件,都可以装配到一个对象中,但产生的运行结果又不相同时
  • 产品类非常复杂,或者产品类中的调用顺序不同产生不同的作用
  • 当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时

下面从一个Person例子进行分析重叠构造器模式、JavaBeans模式、Builder模式的使用。Person类有两个必要参数(id和name),有5个可选参数(age,sex,phone,address和desc)

重叠构造器模式

在这种模式下,你提供第一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,依此类推,最后一个构造器包含所有的可选参数。下面看看其编程实现:

/ * 使用重叠构造器模式
 */
public class Person {
 //必要参数
 private final int id;
 private final String name;
 //可选参数
 private final int age;
 private final String sex;
 private final String phone;
 private final String address;
 private final String desc;
 public Person(int id, String name) {
 this(id, name, 0);
 }
 public Person(int id, String name, int age) {
 this(id, name, age, "");
 }
 public Person(int id, String name, int age, String sex) {
 this(id, name, age, sex, "");
 }
 public Person(int id, String name, int age, String sex, String phone) {
 this(id, name, age, sex, phone, "");
 }
 public Person(int id, String name, int age, String sex, String phone, String address) {
 this(id, name, age, sex, phone, address, "");
 }
 public Person(int id, String name, int age, String sex, String phone, String address, String desc) {
 this.id = id;
 this.name = name;
 this.age = age;
 this.sex = sex;
 this.phone = phone;
 this.address = address;
 this.desc = desc;
 }
}

从上面的代码中,当你想要创建实例的时候,就利用参数列表最短的构造器,但该列表中包含了要设置的所有参数:

Person person = new Persion(1, "李四", 20, "男", "18800000000", "China", "测试使用重叠构造器模式");

重叠构造器可行,但是当有许多参数的时候,创建使用代码会很难写,并且较难以阅读

JavaBeans模式

采用Javabean 的写法,写一堆属性的setter方法,通过生成对象,让后调用setter方法给属性赋值。

/ * 使用JavaBeans模式
 */
public class Person {
 //必要参数
 private int id;
 private String name;
 //可选参数
 private int age;
 private String sex;
 private String phone;
 private String address;
 private String desc;
 public void setId(int id) {
 this.id = id;
 }
 public void setName(String name) {
 this.name = name;
 }
 public void setAge(int age) {
 this.age = age;
 }
 public void setSex(String sex) {
 this.sex = sex;
 }
 public void setPhone(String phone) {
 this.phone = phone;
 }
 public void setAddress(String address) {
 this.address = address;
 }
 public void setDesc(String desc) {
 this.desc = desc;
 }

这种模式弥补了重叠构造器模式的不足。创建实例很容易,这样产生的代码读起来也很容易:

Person person = new Person();
person.setId(1);
person.setName("李四");
person.setAge(20);
person.setSex("男");
person.setPhone("18800000000");
person.setAddress("China");
person.setDesc("测试使用JavaBeans模式");

JavaBeans模式因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。

Builder模式

Builder模式既能保证像重叠构造器那样的安全,也能实现JavaBean模式那样的可读性。

/**
 * 使用Builder模式
 */
public class Person {
 //必要参数
 private final int id;
 private final String name;
 //可选参数
 private final int age;
 private final String sex;
 private final String phone;
 private final String address;
 private final String desc;
 private Person(Builder builder) {
 this.id = builder.id;
 this.name = builder.name;
 this.age = builder.age;
 this.sex = builder.sex;
 this.phone = builder.phone;
 this.address = builder.address;
 this.desc = builder.desc;
 }
 public static class Builder {
 //必要参数
 private final int id;
 private final String name;
 //可选参数
 private int age;
 private String sex;
 private String phone;
 private String address;
 private String desc;
 public Builder(int id, String name) {
  this.id = id;
  this.name = name;
 }
 public Builder age(int val) {
  this.age = val;
  return this;
 }
 public Builder sex(String val) {
  this.sex = val;
  return this;
 }
 public Builder phone(String val) {
  this.phone = val;
  return this;
 }
 public Builder address(String val) {
  this.address = val;
  return this;
 }
 public Builder desc(String val) {
  this.desc = val;
  return this;
 }
 public Person build() {
  return new Person(this);
 }
 }
}

Person是不可变得,所有的默认参数值都单独放在一个地方。builder的setter方法返回builder本身,以便可以链式调用。下面是客户端使用代码:

Person person = new Person.Builder(1, "张三")
                .age(18).sex("男").desc("测试使用builder模式").build();

Android源码中的Builder模式

  • AlertDialog源码
  • Universal-Image-Loader图片库
  • OkHttp的Request源码

优点:

  • 良好的封装性,使用建造者模式可以使客户端不比知道产品内部组成的细节
  • 建造者独立,容易扩展(可通过抽象———接口,抽象类)

缺点:

  • 会产生多余的Builder对象以及Director对象,消耗内存

总结 :Builder模式通常作为配置类的构建器将配置的构建和表示分离开来,同时也是将配置从目标类中隔离出来,避免过多的setter方法。

Javascript 相关文章推荐
Javascript异步编程的4种方法让你写出更出色的程序
Jan 17 Javascript
解析JavaScript中delete操作符不能删除的对象
Dec 03 Javascript
JavaScript实现网页对象拖放功能的方法
Apr 15 Javascript
使用BootStrap建立响应式网页——通栏轮播图(carousel)
Dec 21 Javascript
使用jQuery的ajax方法向服务器发出get和post请求的方法
Jan 13 Javascript
详解angularjs中如何实现控制器和指令之间交互
May 31 Javascript
jQueryeasyui 中如何使用datetimebox 取两个日期间相隔的天数
Jun 13 jQuery
微信小程序HTTP接口请求封装代码实例
Sep 05 Javascript
使用layui日期控件laydate对开始和结束时间进行联动控制的方法
Sep 06 Javascript
javascript如何使用函数random来实现课堂随机点名方法详解
Jul 28 Javascript
快速解决Vue、element-ui的resetFields()方法重置表单无效的问题
Aug 12 Javascript
React中的Context应用场景分析
Jun 11 Javascript
使用vue-route 的 beforeEach 实现导航守卫(路由跳转前验证登录)功能
Mar 22 #Javascript
收集前端面试题之url、href、src
Mar 22 #Javascript
vue 的keep-alive缓存功能的实现
Mar 22 #Javascript
bootstrap中selectpicker下拉框使用方法实例
Mar 22 #Javascript
使用Vue开发动态刷新Echarts组件的教程详解
Mar 22 #Javascript
JavaScript分步实现一个出生日期的正则表达式
Mar 22 #Javascript
vuex 的简单使用
Mar 22 #Javascript
You might like
解决更换PHP5.4以上版本后Dedecms后台登录空白问题的方法
2015/10/23 PHP
详解PHP中array_rand函数的使用方法
2016/09/11 PHP
PHP实现将标点符号正则替换为空格的方法
2017/08/09 PHP
PHP sdk文档处理常用代码示例解析
2020/12/09 PHP
jQuery基础知识小结
2014/12/22 Javascript
基于jquery实现图片上传本地预览功能
2016/01/08 Javascript
JS中使用apply、bind实现为函数或者类传入动态个数的参数
2016/04/26 Javascript
JS实现仿百度文库评分功能
2017/01/12 Javascript
node.js中fs.stat与fs.fstat的区别详解
2017/06/01 Javascript
zTree异步加载展开第一级节点的实现方法
2017/09/05 Javascript
React 使用recharts实现散点地图的示例代码
2018/12/07 Javascript
layui 数据表格 点击分页按钮 监听事件的实例
2019/09/02 Javascript
CountUp.js数字滚动插件使用方法详解
2019/10/17 Javascript
[55:35]VGJ.S vs Mski Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
python线程锁(thread)学习示例
2013/12/04 Python
Python模拟脉冲星伪信号频率实例代码
2018/01/03 Python
python针对excel的操作技巧
2018/03/13 Python
Python实现将json文件中向量写入Excel的方法
2018/03/26 Python
解决Tensorflow使用pip安装后没有model目录的问题
2018/06/13 Python
python用opencv批量截取图像指定区域的方法
2019/01/24 Python
将python文件打包成EXE应用程序的方法
2019/05/22 Python
Python直接赋值、浅拷贝与深度拷贝实例分析
2019/06/18 Python
pandas中DataFrame修改index、columns名的方法示例
2019/08/02 Python
PyTorch中Tensor的维度变换实现
2019/08/18 Python
python将三维数组展开成二维数组的实现
2019/11/30 Python
python实现批量处理将图片粘贴到另一张图片上并保存
2019/12/12 Python
Python插入Elasticsearch操作方法解析
2020/01/19 Python
python 6行代码制作月历生成器
2020/09/18 Python
html5构建触屏网站之网站尺寸探讨
2013/01/07 HTML / CSS
几个解决兼容IE6\7\8不支持html5标签的几个方法
2013/01/07 HTML / CSS
出纳岗位职责
2013/11/09 职场文书
竞聘副主任科员演讲稿
2014/01/11 职场文书
银行员工考核评语
2014/12/31 职场文书
《圆明园的毁灭》教学反思
2016/02/16 职场文书
十大最强火系宝可梦,喷火龙上榜,第一名有双火属性
2022/03/18 日漫
如何更改Win11声音输出设备?Win11声音输出设备四种更改方法
2022/04/08 数码科技