创建Java对象时,对于可为空的属性,创建对象的时候有3种模式:重叠构造器模式、JavaBeans模式、Builder模式(推荐)、Stream模式(推荐)。


                                                            重叠构造器模式

     该模式使用多个构造器创建Java对象。
     该写法符合Java的标准惯例,但是随着参数的越来越多,代码变得越来越难写。而且该方式灵活性低,可读性较差,客户端想要知道哪些值的具体含义,还需要仔细数参数,而且还容易写错参数的位置。 
package effectiveJava.builder;

public class NutritionFactsMultiContr {
//食物尺寸
private int servingSize;
//食物数量
private int servings;
//热量(卡路里)
private int calories;
//脂肪含量
private int fat;
//食用盐(钠)含量
private int sodium;
//糖类含量
private int carbohydrate; public NutritionFactsMultiContr(int servingSize, int servings) {
this(servingSize,servings,0);
} public NutritionFactsMultiContr(int servingSize, int servings, int calories) {
this(servingSize,servings,calories,0);
} public NutritionFactsMultiContr(int servingSize, int servings, int calories, int fat) {
this(servingSize,servings,calories,fat,0);
} public NutritionFactsMultiContr(int servingSize, int servings, int calories, int fat, int sodium) {
this(servingSize,servings,calories,fat,sodium,0);
} public NutritionFactsMultiContr(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
} public static void main(String[] args) {
NutritionFactsMultiContr nutritionFacts = new NutritionFactsMultiContr(1,2,3,4,5,6);
} }

  


                                                    JavaBeans模式

     
      该模式通过调用一个无参构造器来创建对象,并使用setter方法来设置参数值。
      该模式弥补了重叠构造器模式的不足,而且创造实例很容易,代码的可读性也高。但是JavaBeans模式将构造过程分到几个步骤中,在构造过程中JavaBean可能处于不一致的状态,导致一些未知的错误。同时,JavaBeans模式阻止了把类做成不可变的可能。
package effectiveJava.builder;
//营养成分
public class NutritionFactsSetter { //食物尺寸
private int servingSize;
//食物数量
private int servings;
//热量(卡路里)
private int calories;
//脂肪含量
private int fat;
//食用盐(钠)含量
private int sodium;
//糖类含量
private int carbohydrate; public void setServingSize(int servingSize) {
this.servingSize = servingSize;
} public void setServings(int servings) {
this.servings = servings;
} public void setCalories(int calories) {
this.calories = calories;
} public void setFat(int fat) {
this.fat = fat;
} public void setSodium(int sodium) {
this.sodium = sodium;
} public void setCarbohydrate(int carbohydrate) {
this.carbohydrate = carbohydrate;
} public static void main(String[] args) {
NutritionFactsSetter nutritionFacts = new NutritionFactsSetter();
nutritionFacts.setCalories(1);
nutritionFacts.setCarbohydrate(2);
}
}

  


                                                                       Builder模式

 
    该模式不直接生成想要的对象,而是先创建一个builder对象,再在builder上调用类似setter的方法设置参数值,最后调用无参的build方法来生成所需要的对象。(注意:Builder模式下,想要创建的对象的构造器是私有的,这样创建出来的对象是不可变的)
     该模式既能像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那样的可读性,同时实现了对象的不可变性。但是Builder模式为了创建对象,必须先创建它的构建器,导致代码有点冗余。
     Builder模式模拟了具名的可选参数。
package effectiveJava.builder;
//营养成分
public class NutritionFacts { //食物尺寸
private int servingSize;
//食物数量
private int servings;
//热量(卡路里)
private int calories;
//脂肪含量
private int fat;
//食用盐(钠)含量
private int sodium;
//糖类含量
private int carbohydrate; /**
* NutritionFacts是不可变的,不对外提供构造器
* @param builder
*/
private NutritionFacts(Builder builder) {
this.servingSize = builder.servingSize;
this.servings = builder.servings;
this.calories = builder.calories;
this.fat = builder.fat;
this.sodium = builder.sodium;
this.carbohydrate = builder.carbohydrate;
} public static class Builder {
private int servingSize;
private int servings;
private int calories;
private int fat;
private int sodium;
private int carbohydrate; //必填字段
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
} //可选字段
public Builder calories(int val){
this.calories = val;
return this;
} public Builder fat(int val){
this.fat = val;
return this;
} public Builder sodium(int val){
this.sodium = val;
return this;
} public Builder carbohydrate(int val){
this.carbohydrate = val;
return this;
} public NutritionFacts build() {
return new NutritionFacts(this);
}
} public static void main(String[] args) {
NutritionFacts facts = new NutritionFacts.Builder(1, 2).calories(3).fat(4).build();
}
}

  


                                                                    Stream模式

   
    Java8中引入了一种新特性Stream,这让编码变得更加简单易读(其实,该思想在以前的JDK版本中也有使用,例如:StringBuilder、StringBuffer)。在对象的创建过程中,我们也可以使用Stream思想。
    Stream模式就是将setter方法的返回值变为对象本身,这样就可以连续调用setter方法。
package effectiveJava.builder;

public class NutritionFactsStream {
//食物尺寸
private int servingSize;
//食物数量
private int servings;
//热量(卡路里)
private int calories;
//脂肪含量
private int fat;
//食用盐(钠)含量
private int sodium;
//糖类含量
private int carbohydrate; public NutritionFactsStream() {
} public int getServingSize() {
return servingSize;
} public NutritionFactsStream setServingSize(int servingSize) {
this.servingSize = servingSize;
return this;
} public int getServings() {
return servings;
} public NutritionFactsStream setServings(int servings) {
this.servings = servings;
return this;
} public int getCalories() {
return calories;
} public NutritionFactsStream setCalories(int calories) {
this.calories = calories;
return this;
} public int getFat() {
return fat;
} public NutritionFactsStream setFat(int fat) {
this.fat = fat;
return this;
} public int getSodium() {
return sodium;
} public NutritionFactsStream setSodium(int sodium) {
this.sodium = sodium;
return this;
} public int getCarbohydrate() {
return carbohydrate;
} public NutritionFactsStream setCarbohydrate(int carbohydrate) {
this.carbohydrate = carbohydrate;
return this;
} public static void main(String[] args) {
NutritionFactsStream nutritionFacts = new NutritionFactsStream().setServings(1).setServings(2);
}
}

 

此外,创建对象的模式还有很多,比如:工厂模式、单例模式等,不是本文讨论的重点,有兴趣的可以自己研究一下。

参考资料:

  • Joshua Bloch 《Effective Java》
 

Java对象创建模式的更多相关文章

  1. 设计模式---对象创建模式之原型模式(prototype)

    一:概念 原型模式(Prototype Pattern) 实际上就是动态抽取当前对象运行时的状态 Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例.使用Protot ...

  2. 深入理解JavaScript系列(48):对象创建模式(下篇)

    介绍 本篇主要是介绍创建对象方面的模式的下篇,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式6:函数语法糖 函数语法糖是为一个对象快速添加方法(函数)的扩展,这个主要是利用pro ...

  3. 深入学习Java对象创建的过程:类的初始化与实例化

    在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类构造器完 ...

  4. 《JavaScript 模式》读书笔记(5)— 对象创建模式4

    我们学完了大部分对象创建模式相关的内容,下面还有一些小而精的部分. 七.对象常量 JavaScript中没有常量的概念,虽然许多现代的编程环境可能为您提供了用以创建常量的const语句.作为一种变通方 ...

  5. 《JavaScript模式》第5章 对象创建模式

    @by Ruth92(转载请注明出处) 第5章:对象创建模式 JavaScript 是一种简洁明了的语言,并没有其他语言中经常使用的一些特殊语法特征,如 命名空间.模块.包.私有属性 以及 静态成员 ...

  6. 《Javascript模式》之对象创建模式读书笔记

    引言: 在javascript中创建对象是很容易的,可以使用对象字面量或者构造函数或者object.creat.在接下来的介绍中,我们将越过这些方法去寻求一些其他的对象创建模式. 我们知道js是一种简 ...

  7. 设计模式---对象创建模式之工厂方法模式(Factory Method)

    前提:“对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式(表现最为突出) 工 ...

  8. C++设计模式 之 “对象创建”模式:Factory Method、Abstract Factory、Prototype、Builder

    part 0 “对象创建”模式 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式 Fact ...

  9. 深入理解JavaScript系列(47):对象创建模式(上篇)

    介绍 本篇主要是介绍创建对象方面的模式,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式1:命名空间(namespace) 命名空间可以减少全局命名所需的数量,避免命名冲突或过度. ...

随机推荐

  1. Nginx 如何自定义变量?

    之前的两篇文章 Nginx 变量介绍以及利用 Nginx 变量做防盗链 讲的是 Nginx 有哪些变量以及一个常见的应用.那么如此灵活的 Nginx 怎么能不支持自定义变量呢,今天的文章就来说一下自定 ...

  2. 手机U盘制作成系统启动盘后在手机端无法识别

    本人最近用手机U盘做了个系统启动盘,突然发现U盘再次插到手机的时候,手机无法识别出U盘了,于是百度了一下,百度结果大概是跟U盘的格式有关.结果我想起了之前用的DiskGenius可以看到u盘的隐藏盘符 ...

  3. v-forv-for指令的三种使用方法

    1.迭代数组 <p v-for="(item,i) in list">id:{{item.id}}---名字:{{item.name}}---索引{{item.age} ...

  4. elasticSearch插件的安装以及使用nginx的modles收集nginx的日志

    1.首先在windows环境上搭建es的集群 集群的配置如下 #node01的配置: cluster.name: es-itcast-cluster node.name: node01 node.ma ...

  5. Python3-configparser模块-配置文件解析器

    Python3中的configparser模块主要用于处理类似于windows ini 文件结构的配置文件 1.configparser模块提供实现基本配置语言的ConfigParser类 2.配置文 ...

  6. Python3-cx_Oracle模块-数据库操作之Oracle

    模块安装 1.安装cx_Oracle模块之前必须要安装Oracle客户端,否则无法使用 2.系统上需要装有对应版本的c++编译套件(Linux下:g++ Windows下:VC++) 参考文档 htt ...

  7. 千金良方说:"我现在奉上179341字的MySQL资料包,还来得及吗?有"代码段、附录、和高清图!!"

    上一篇"上发布过"一不小心,我就上传了 279674 字的 MySQL 学习资料到 github 上了",我在更早之前,在微信公众号"老叶茶馆"上发布 ...

  8. 入门大数据---Hbase_Java_API

    一.简述 截至到目前 (2019.04),HBase 有两个主要的版本,分别是 1.x 和 2.x ,两个版本的 Java API 有所不同,1.x 中某些方法在 2.x 中被标识为 @depreca ...

  9. python在循环中追加字典

    1. 在循环中用append增加key值,最终生成全是key值的list: 2. 在循环中用append增加value值,最终生成全是value值的list: 3. 最后用zip将两个list合并成一 ...

  10. CodeForces 1293 C NEKO's Maze Game

    [题目链接] [题目大意] 有一个2 ∗ n的地图,小女孩从(1,1)想移动到(2,n) 有q次询问,每次询问更改一个格子状态(是否可以通过) 只能上下左右移动而不能斜着移动,问每次操作后,是否可以移 ...