【问题标题】:Calling private methods from inside the constructor in Java从Java中的构造函数内部调用私有方法
【发布时间】:2018-07-31 13:02:18
【问题描述】:

我有以下课程:

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 将类字段公开给外部类。但是,问题是这些字段只有在调用 ChopraChap7SeasonalFactorsCalculator() 方法后才能获得任何值。所以,我在这里所做的是在创建类的对象后立即调用该方法。当然,这会起作用,但这是好的设计模式吗?

假设我不会从构造函数中调用该方法。所以,如果我们有下面的代码是一些其他的类:

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

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

在我的情况下,最好的设计模式是什么?

【问题讨论】:

  • 这个getSales() { if(sales == null){// call here u r method}}怎么样
  • 哇,好漂亮。我在某处读到,getter 用于此类额外代码,而不是简单地返回变量的值。赞成。你也可以添加这个作为答案吗?
  • Getter 应该获取当前值而不是进行复杂的初始化。想象一下,您添加了另一个方法,例如 public calculateSales(),它在内部使用 sales 字段而不调用 getter - 它会失败
  • 有一个类似的问题; Can I call methods in constructor in Java? 那里接受的答案建议使用工厂模式。这可能是另一种选择。

标签: java design-patterns


【解决方案1】:

当然,这会起作用,但这是好的设计模式吗?

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

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

对于任何方法或代码块,您担心有人更改构造函数中的某些内容可能是正确的。
但是应用程序的设计并不是为了检查每个组件是否符合我们的期望。这是单元测试的角色,用于断言实际行为是预期的。

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

【讨论】:

  • 应该注意的是,构造函数不应该调用可以被覆盖的方法(例如,非私有且未标记为 final 或在 final 类中的方法)。如果子类重写了这个方法,它可以在对象的字段完全构造(稳定)之前访问它们。
  • @Justin Albano 我完全同意这一点。它没有明确说明,但这就是我指定private 方法的原因。
【解决方案2】:

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

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

一个类包含被调用来创建对象的构造函数 类蓝图。

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

【讨论】:

  • 另外,我可以按照@malikarjun 的建议检查 getter 本身中的空字段或空字段。
  • 是的,但我认为这会破坏 OOP 中的 SOLID 原则。 Getter 应该获取当前值,而不是进行复杂的初始化。想象一下,您添加了另一个方法,例如 calculateSales(),它在内部使用 sales 字段而不调用 getter - 它会失败
  • 是的。我将不得不多次调用它。完全正确。
  • 是的,所以当您可以在构造函数中初始化它时,基本上没有必要延迟它并担心您的对象是否处于可用状态。这就是为什么你有构造函数,否则你就不必制作一个
猜你喜欢
  • 2016-08-16
  • 1970-01-01
  • 2017-07-13
  • 1970-01-01
  • 2015-12-15
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
  • 2016-07-31
相关资源
最近更新 更多