关于设计模式:在Java中从构造函数内部调用私有方法

Calling private methods from inside the constructor in 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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.tesco.demandforecasting.group8.choprachap7;

import java.util.ArrayList;

import com.tesco.demandforecasting.group8.utils.MathOperUtils;
import com.tesco.demandforecasting.group8.utils.RegressionUtils;

import lombok.Getter;

/**
 * This class if used to find seasonality factor of each period, as explain in
 * the chapter See https://kelley.iu.edu/mabert/e730/Chopra-Chap-7.pdf for the
 * explanation
 */

@Getter
public class ChopraChap7SeasonalFactorsCalculator {

    private double[] regressionParams;

    private int sales_size;
    private int periodicity;

    private ArrayList<Integer> sales;
    private ArrayList<Double> deseasonalisedData;
    private ArrayList<Double> deseasonalisedDemandUsingRegression;
    private ArrayList<Double> seasonalityFactors;

    public ChopraChap7SeasonalFactorsCalculator() {

        this.sales = new ArrayList<>();
        this.deseasonalisedData = new ArrayList<>();
        this.deseasonalisedDemandUsingRegression = new ArrayList<>();
        this.seasonalityFactors = new ArrayList<>();

        this.sales.add(8000);
        this.sales.add(13000);
        this.sales.add(23000);
        this.sales.add(34000);
        this.sales.add(10000);
        this.sales.add(18000);
        this.sales.add(23000);
        this.sales.add(38000);
        this.sales.add(12000);
        this.sales.add(13000);
        this.sales.add(32000);
        this.sales.add(41000);

        this.sales_size = sales.size();
        this.periodicity = 4;

        calculateSeasonalityFactors();
    }


    private void calculateSeasonalityFactors() {

        .......
        .......

        this.seasonalityFactors = seasonalityFactors;
        this.deseasonalisedDemandUsingRegression = deseasonalisedDemandUsingRegression;
        this.deseasonalisedData = deseasonalisedData;

    }

}

我想使用它们各自的getter将类字段公开给外部类。但是,问题是,这些字段只有在调用choprachp7QuartalFactorScalCalculator()方法之后才能获得任何值。所以,我在这里所做的就是在创建类的对象后立即调用方法。当然,这是可行的,但这是一个好的设计模式吗?

假设我不会从构造函数调用该方法。因此,如果我们有以下代码,那就是其他类:

1
2
ChopraChap7SeasonalFactorsCalculator calc = new ChopraChap7SeasonalFactorsCalculator();
calc.getDeseasonalisedData();

这将返回给我任何空数组列表。如何确保在访问任何字段之前调用该方法?

在我的例子中,最好的设计模式是什么?


Of course, this will work, but is this good design pattern?

这是一个非常正确的设计。您将构造函数逻辑的一部分委托给一个私有方法,以使事情更清楚。

This will return to me any empty array list. How do I ensure that the
method is called before any field is accessed?

对于任何方法或代码块,对构造函数中的某些更改的恐惧都可能是真的。但是应用程序的设计并不是为了检查每个组件是否按照我们期望的方式工作。这是单元测试角色,用于断言实际行为是预期的行为。

因此,为ChopraChap7SeasonalFactorsCalculator构造函数编写一个单元测试,在这个测试中,断言一旦创建了对象,所有getter都会返回预期值。如果有人以不正确的方式修改构造函数,测试将失败,构建也将失败。你现在有办法确保事情按预期进行。


我觉得很好。构造器用于创建有用的对象。如果您确定没有设置这些对象就不能使用,那么就没有理由不在构造函数中设置它们。

如果检查https://docs.oracle.com/javase/tutorial/java/javaoo/constructors.html

A class contains constructors that are invoked to create objects from
the class blueprint.

您已经添加了字段,但如果不设置这些字段,就没有工作对象,显然您已经知道这些值了。最好的方法是将这些留在构造函数中。如果为了创建该类的实例而有一些未知的值或需求,您可以考虑工厂模式或其他东西,但在您的情况下,构造函数的用法是很好的。