简体   繁体   中英

Calling private methods from inside the constructor in Java

I have the following class:

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;

    }

}

I want to expose the class fields to external classes, using their respective getters. But, the problem is that those fields attain any value only after the ChopraChap7SeasonalFactorsCalculator() method is called. So, what I have done here is call the method as soon as an object of the class is created. Of course, this will work, but is this good design pattern?

Supposing I would not have called the method from the constructor. So, if we have the following code is some other class:

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

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

What would be the best design pattern in my case?

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

This is a very correct design. You delegate a part of the constructor logic into a private method to make things clearer.

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

Your fear about someone changes something in the constructor may be true for any methods or chunks of code.
But applications are not designed to check that each component does what we expect from it. This is the unit tests role to assert that the actual behavior is which one expected.

So write an unit test for the ChopraChap7SeasonalFactorsCalculator constructor and in this test assert that all getters return the expected values once the object is created.
If someone modifies the constructor in an incorrect way, the test will fail and the build too. You have your way to make sure things are as expected now.

I think that's pretty fine. The constructor is there to create a useful object. If you are sure the object cannot be used without these being set there is no reason why not to set them in the constructor.

If you check https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html

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

You have added the fields but you don't have a working object without these being set and apparently you know the values already. The best way to do it would be leave these in the constructor. If there are some unknown values or requirements in order to create an instance of that class you can consider Factory pattern or something but in your case constructor usage is just fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM