Java对象创建模式
创建Java对象时,对于可为空的属性,创建对象的时候有3种模式:重叠构造器模式、JavaBeans模式、Builder模式(推荐)、Stream模式(推荐)。
重叠构造器模式
该模式使用多个构造器创建Java对象。
该写法符合Java的标准惯例,但是随着参数的越来越多,代码变得越来越难写。而且该方式灵活性低,可读性较差,客户端想要知道哪些值的具体含义,还需要仔细数参数,而且还容易写错参数的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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模式阻止了把类做成不可变的可能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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模式模拟了具名的可选参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 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方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 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》
更多内容,请访问:http://www.cnblogs.com/BlueStarWei
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix