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》
 
posted @   blue星空  阅读(414)  评论(1编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· 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
点击右上角即可分享
微信分享提示