我们在平常类的构建过程中,可能会面临很多问题,可扩张性、安全性等等。想象一下,这样一个场景,我们现在要创建一个类,其中有6个属性,其中又有4个属性的值是不太确定的(可能某个对象就不需要其中的某个值),这时我们怎么创建这个类呢?以下是几种方法:
使用普通构造器
public class Test {
private int servingSize;
private int servings;
private int calories;
private int fat;
private int sodium;
private int carbohydrate; public Test(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = 0;
} public Test(int servingSize, int servings, int calories) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = 0;
} public Test(int servingSize, int servings, int calories, int fat) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = 0;
} public Test(int servingSize, int servings, int calories, int fat, int sodium) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = 0;
} public Test(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) {
Test test = new Test(1,2,3,0,5,6);
}
如上所示,在实例化对象时,我们需要传入相应的值,这时发现:
- 第四个参数不是我们需要的,但是还不得不给他传递一个值
- 我们在传值时,很容易出错,某两个参数值互换了位置,这在工作时是不好发现的,但是程序会报错
所以上面的方式在涉及到参数比较多,而且参数值不太确定是否需要时,这种方法会给我们的编码以及后期维护带来很大的困扰,我们再改进一下。
JavaBeans模式
public class Test {
private int servingSize;
private int servings;
private int calories;
private int fat;
private int sodium;
private int carbohydrate; public Test() { } 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;
} }
如上,我们先创建一个无参构造方法(可以不写出来,会默认创建),接下来就是利用setter方法给属性赋值
public static void main(String[] args) {
Test test = new Test();
test.setServingSize(1);
test.setCalories(2);
test.setCalories(3);
test.setSodium(5);
test.setCarbohydrate(6);
}
如上,我们需要的对象不需要fat属性,我们就不用给其赋值,这中方法有几个好处:
- 客户端调用简单,也就是实例化对象的过程十分简单,并且不会出现把值传递出错的风险
- 别人能够很好的使用且理解简单
但是我们知道,javaBeans有个缺点:
- 线程不安全,因为对象的创建分在了好几步的过程中,不能保证对象状态的一致性
我们可以确保线程的安全,这就需要我们额外的精力(我们可以在对象构造完成,并且不允许在冻结之前使用时,手动冻结,实际中很少使用,编译器无法确定我们是否调用的freeze方法
)。因此这种方法也不够理想,还有什么继续改进的地方吗?
构建器(建造者模式的一种形式)
public class Test {
private int servingSize;
private int servings;
private int calories;
private int fat;
private int sodium;
private int 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 calories) {
calories = calories;
return this;
} public Builder fat(int fat) {
fat = fat;
return this;
} public Builder sodium(int sodium) {
sodium = sodium;
return this;
} public Builder carbohydrate(int carbohydrate) {
carbohydrate = carbohydrate;
return this;
} public Test builder () {
return new Test(this);
}
} private Test(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
调用方式:
public static void main(String[] args) {
Test test = new Builder(1,2).calories(3).fat(4).sodium(5).carbohydrate(6).builder();
}
这样就保证了对象在不变的情况下,简单明了地实现了对象实例化(至于代码中的内部类,我们以后细说)。
Java构造器与构建器的使用的更多相关文章
-
java构造器和构建器
本文摘自:https://blog.csdn.net/wh2827991/article/details/79013115 在实例化一个类的过程中,通常会遇到多个参数的构造函数,但如果有些参数是非必需 ...
-
深入探索Java设计模式之构建器模式(五)
抽丝剥茧 细说架构那些事——[优锐课] 简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类.大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性.宏伟 ...
-
Java基础——字符串构建器
StringBuilder类: 可以将许多小段的字符串构建一个字符串. StringBuilder builder = new StringBuilder(); //构造一个空的字符串构建器 buil ...
-
effective java之使用构建器来创建对象
第二章第2条:遇到多个构造器参数时要考虑使用构建器(builder) 就是建造者模式(不直接生成想要的对象,而是让客户端利用所有有必要的参数调用构造器或者静态工厂)直接上代码 package com. ...
-
【转】通过lombok带你读透Builder构建器
原地址:https://www.jianshu.com/p/0d8fc3df3647?from=timeline&isappinstalled=0 很久之前,我在<effective j ...
-
Java 构造器 遇到多个构造器时要考虑用构建器
静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数. 当一个类中有若干个必选属性和多个可选属性时,采用重叠构造器模式.JavaBeans模式或者Builder模式,但各有优劣. 当 ...
-
【读书笔记 - Effective Java】02. 遇到多个构造器参数时要考虑用构建器
类有多个可选参数的解决方案: 1. 重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写,并且仍然较难以阅读. 2. JavaBeans模式,调用一个无参构造器来创造对象,然后调用sett ...
-
Java构建器(多个构造器参数)
今天看netty权威指南,第一次听说构建器,百度了几个博客,但是并没有通俗易懂一点儿的,综合别人的博客,总结如下: 1. 构建器是什么? 当创建对象需要传入多个参数的时候我们通常会根据参数的数量写不同 ...
-
Effective JAVA 创建和销毁对象 遇到多参构造器考虑使用构建器
//构建器抽象类,为不同类的实现提供 public interface Builder<T> { public T build(); } /** * @描述: 营养表 */ public ...
随机推荐
-
我为NET狂官方面试题-数据库篇
求结果:select "1"? 查找包含"objs"的表?查找包含"o"的数据库? 求今天距离2002年有多少年,多少天? 请用一句SQL获 ...
-
创建Google网站地图Sitemap.xml
Sitemap.xml是google搞出来的,也就是网站地图,不过这个网站地图是用xml写的,而且要按google的标准来写,并且要将写出来的这个文件sitemap.xml上传到自己的服务器空间中去. ...
-
SandDock 应用示例
直接上代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data ...
-
jquery dialog-优雅的弹出框
前面一章已经对datepicker的使用,做了简单的说明.这一章主要对dialog如何使用做个说明. jquery ui-dialog在web开发中运用还是比较多的.最常见的例子就是登 ...
-
Lua 服务器与客户端实例(转)
=============================================================== 服务器,main.lua ======================= ...
-
Codeforces 842B Gleb And Pizza【几何,水】
B. Gleb And Pizza time limit per test:2 seconds memory limit per test:256 megabytes input:standard i ...
-
DirectX SDK (June 2010)安装错误S1023的一个解决方法
在安装DXSDK_Jun10.exe时一个常见的安装失败的代号是S1023,一般出现这种错误的原因是系统中已经安装了Visual Studio 2010及以上的版本. 在[控制面板]中找到这两个: 如 ...
-
PLC 通讯
几个之前整理的高级语言与PLC通讯的资源下载链接:三菱:http://blog.sina.com.cn/s/blog_16d7d3ecb0102x6wj.html倍福:http://bbs.elecf ...
-
pytest.10.使用fixture参数化测试预期结果
From: http://www.testclass.net/pytest/test_api_with_expected_result/ 背景 接上一节v2ex网站的查看论坛节点信息的api. 我们在 ...
-
f5会话保持导致站点访问故障
1.环境: vs Service Port为443和80,vip为10.160.100.66,pool为10.160.45.42/43的8080.80的vs重新到443. 2.问题: 单独访问源站都没 ...