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 相关文章推荐
css把超出的部分显示为省略号的方法兼容火狐
Jul 23 Javascript
jquery offset函数应用实例
Nov 14 Javascript
jQuery 的全选(全非选)即取得被选中的值使用介绍
Nov 12 Javascript
js判读浏览器是否支持html5的canvas的代码
Nov 18 Javascript
javascript结合canvas实现图片旋转效果
May 03 Javascript
Jquery实现仿京东商城省市联动菜单
Nov 19 Javascript
JS控制层作圆周运动的方法
Jun 20 Javascript
javascript实现随机生成DIV背景色
Jun 20 Javascript
利用BootStrap的Carousel.js实现轮播图动画效果
Dec 21 Javascript
基于JS设计12306登录页面
Dec 28 Javascript
浅谈gulp创建完整的项目流程
Dec 20 Javascript
垃圾回收器的相关知识点总结
May 13 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
destoon利用Rewrite规则设置网站安全
2014/06/21 PHP
php简单实现多字节字符串翻转的方法
2015/03/31 PHP
PHP封装的完整分页类示例
2018/08/21 PHP
PHP通过调用新浪API生成t.cn格式短网址链接的方法详解
2019/02/20 PHP
javascript打印输出json实例
2013/11/11 Javascript
jQuery照片伸缩效果不影响其他元素的布局
2014/05/09 Javascript
JavaScript字符串对象charAt方法入门实例(用于取得指定位置的字符)
2014/10/17 Javascript
两种JS实现屏蔽鼠标右键的方法
2020/08/20 Javascript
jQuery日历插件datepicker用法详解
2016/03/03 Javascript
基于VUE选择上传图片并页面显示(图片可删除)
2017/05/25 Javascript
简单谈谈js的数据类型
2017/09/25 Javascript
vue mounted组件的使用
2018/06/18 Javascript
React Native基础入门之调试React Native应用的一小步
2018/07/02 Javascript
JavaScript中AOP的实现与应用
2019/05/06 Javascript
Vue.js递归组件实现组织架构树和选人功能
2019/07/04 Javascript
JavaScript实现网页计算器功能
2020/10/29 Javascript
[06:35]2014DOTA2国际邀请赛 老男孩梦圆西雅图中国军团世界最强
2014/07/22 DOTA
[00:39]DOTA2上海特级锦标赛 Liquid战队宣传片
2016/03/04 DOTA
python查询mysql,返回json的实例
2018/03/26 Python
python获取指定字符串中重复模式最高的字符串方法
2018/06/29 Python
python 实现图片旋转 上下左右 180度旋转的示例
2019/01/24 Python
python判断文件是否存在,不存在就创建一个的实例
2019/02/18 Python
Python实现的矩阵转置与矩阵相乘运算示例
2019/03/26 Python
Django 大文件下载实现过程解析
2019/08/01 Python
Python 解决OPEN读文件报错 ,路径以及r的问题
2019/12/19 Python
关于初始种子自动选取的区域生长实例(python+opencv)
2020/01/16 Python
Linux系统下升级pip的完整步骤
2021/01/31 Python
Lookfantastic俄罗斯:欧洲在线化妆品零售商
2019/08/06 全球购物
计算机开发个人求职信范文
2013/09/26 职场文书
自荐信如何“自荐”
2013/10/24 职场文书
物业保安员岗位职责制度
2014/01/30 职场文书
商务英语专业毕业生求职信
2014/07/06 职场文书
基层党支部整改方案
2014/10/25 职场文书
2015年财务人员工作总结
2015/04/10 职场文书
zabbix agent2 监控oracle数据库的方法
2021/05/13 Oracle
Dubbo+zookeeper搭配分布式服务的过程详解
2022/04/03 Java/Android