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 相关文章推荐
jQuery ctrl+Enter shift+Enter实现代码
Feb 07 Javascript
监控 url fragment变化的js代码
Apr 19 Javascript
对jQuery的事件绑定的一些思考(补充)
Apr 20 Javascript
jQuery循环遍历子节点并获取值的方法
Apr 14 Javascript
Javascript函数中的arguments.callee用法实例分析
Sep 16 Javascript
BootStrap 超链接变按钮的实现方法
Sep 25 Javascript
jQuery命名空间与闭包用法示例
Jan 12 Javascript
js实现本地时间同步功能
Aug 26 Javascript
解决vue的touchStart事件及click事件冲突问题
Jul 21 Javascript
解决vue动态下拉菜单 有数据未反应的问题
Aug 06 Javascript
javascript实现移动端上传图片功能
Aug 18 Javascript
vue响应式原理与双向数据的深入解析
Jun 04 Vue.js
使用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
乱谈我对耳机、音箱的感受
2021/03/02 无线电
Eclipse的PHP插件PHPEclipse安装和使用
2014/07/20 PHP
php之curl设置超时实例
2014/11/03 PHP
php递归实现无限分类的方法
2015/07/28 PHP
php实现的mongoDB单例模式操作类
2018/01/20 PHP
自适应高度框架 ----属个人收藏内容
2007/01/22 Javascript
JavaScript 继承详解 第一篇
2009/08/30 Javascript
JQuery 选项卡效果(JS与HTML的分离)
2010/04/01 Javascript
javascript 设为首页与加入收藏兼容多浏览器代码
2011/01/11 Javascript
js实时获取系统当前时间实例代码
2013/06/28 Javascript
jquery indexOf使用方法
2013/08/19 Javascript
JavaScript设计模式之策略模式实例
2014/10/10 Javascript
javaScript中slice函数用法实例分析
2015/06/08 Javascript
跟我学习javascript的this关键字
2020/05/28 Javascript
基于JavaScript代码实现pc与手机之间的跳转
2015/12/23 Javascript
一种基于浏览器的自动小票机打印实现方案(js版)
2016/07/26 Javascript
详解照片瀑布流效果(js,jquery分别实现与知识点总结)
2017/01/01 Javascript
使用imba.io框架得到比 vue 快50倍的性能基准
2019/06/17 Javascript
Vue请求java服务端并返回数据代码实例
2019/11/28 Javascript
Angular如何由模板生成DOM树的方法
2019/12/23 Javascript
Python版实现微信公众号扫码登陆
2020/05/28 Javascript
详解Django框架中用户的登录和退出的实现
2015/07/23 Python
Python 中的 else详解
2016/04/23 Python
利用pandas读取中文数据集的方法
2018/07/25 Python
10个Python小技巧你值得拥有
2018/09/29 Python
python2与python3中关于对NaN类型数据的判断和转换方法
2018/10/30 Python
python实现图片识别汽车功能
2018/11/30 Python
Python面向对象程序设计示例小结
2019/01/30 Python
python requests指定出口ip的例子
2019/07/25 Python
Python在cmd上打印彩色文字实现过程详解
2019/08/07 Python
Pytorch的mean和std调查实例
2020/01/02 Python
Python3创建Django项目的几种方法(3种)
2020/06/03 Python
用Python开发app后端有优势吗
2020/06/29 Python
世界上最具创新性的增强型知名运动品牌:Proviz
2018/04/03 全球购物
NYX Professional Makeup英国官网:美国平价专业彩妆品牌
2019/11/13 全球购物
MySQL连表查询分组去重的实现示例
2021/07/01 MySQL