【问题标题】:How can I pass an argument to one implementor of an Interface but not the others (without passing it in the constructor)?如何将参数传递给接口的一个实现者而不是其他实现者(而不在构造函数中传递它)?
【发布时间】:2014-07-15 15:59:12
【问题描述】:

我正在开发的应用程序由配置文件和步骤组成。每个 Profile 由多个步骤组成,共有 4 种步骤:

  • 顺序:这一步完成后,依次进入下一步。
  • 跳转 :此步骤完成后,进入带有 ID 的步骤。
  • 已评估 :此步骤完成后,根据某种方法的结果确定下一个步骤 ID。
  • 终端:这一步是最后一步。

我的Step 接口有一个名为public abstract Step getNextStep() 的抽象方法。每个步骤类型都根据需要实现此方法。

问题在于 EvaluatedStep 需要一个参数,我们称之为Parameter p,其他步骤类型都不需要任何参数。

我通过将接口中的方法头更改为public abstract Step getNextStep(Parameter p); 来解决这个问题,但我知道这不是一个好的解决方案。 有什么更好的方法?

注意:

  • 我无法将Parameter p 传递给EvaluationStep 构造函数,因为该参数仅在需要调用getNextStep() 时可用。
  • Parameter p 将来可能是不同参数的集合体,因此该问题的解决方案必须灵活。换句话说,现在我只需要将Parameter p 传递给getNextStep(),但将来我可能需要传递一堆不同的参数getNextStep(Parameter p,Argument a,Something s)如何避免这种情况

【问题讨论】:

  • 接口没有“abstract”关键字。你是指抽象类还是接口?
  • 是的,您不必明确写出来。
  • 我对你如何致电getNextStep()感到困惑。如果你有一个Step 对象(即,你不知道它是什么类型),你必须要么传递参数,要么不传递参数——你怎么知道该做什么?如果你知道你有一个EvaluatedStep,则转换为EvaluatedStep,你可以调用任何你想要的特定于EvaluatedStep的函数(如果你愿意,包括getNextStep()的重载版本)。
  • 类似于Parameter p = getParameter; Step nextStep = currentStep.getNextStep(p)。 getNextStep() 实现选择是否使用参数。
  • 为什么不让接口有 2 个相互重载的方法:1 个带参数,一个不带参数。此外,为了克服灵活性问题,您可以使用自定义对象作为参数,并根据需要简单地添加 getter 和 setter,或者您可以使用像使用哈希表作为参数这样的解决方案。

标签: java design-patterns interface


【解决方案1】:

一种方法是在签名上使用可变参数,如下所示:

pubic abstract Step getNextStep(Object... parameters)

那么它可以通过以下任何一种方式调用:

seq.getNextStep();
eval.getNextStep(p);
future.getNextStep(p,a,s);

所有都将匹配界面。在实现中,如果需要,可以将它们作为数组成员引用:

public Step getNextStep(Object... parameters){
    if ( parameters.length > 0 && parameters[0] instanceof Parameter ){
        Parameter p = (Parameter) parameters[0];
    }
}

【讨论】:

  • 最好定义一些StepParameter 接口,ParameterArgumentSomething 都将扩展。然后您可以将其声明为采用StepParameter... 而不是Object...。否则,你可以用任何东西来调用它,比如StringIntegerRectangle……它不知道如何处理的各种对象。
【解决方案2】:

您应该能够将参数使用者添加到抽象类:

abstract class Step {

    public abstract Step getNextStep();

    public void addParameter(Parameter p) {
    }

    public void addParameter(Argument a) {
    }

    public void addParameter(Something s) {
    }
}

class Evaluated extends Step {

    Parameter p;

    @Override
    public Step getNextStep() {

    }

    @Override
    public void addParameter(Parameter p) {
        this.p = p;
    }

}

【讨论】:

  • 这很聪明。这是如何改进的:我们声明一个名为NextStepResolutionParameter 的新空接口,由ParameterArgumentSomething 实现,那么我们只需要在Step 接口中增加一个方法:addNextStepResolutionParameter(NextStepResolutionParameter p)
  • @W.K.S - 这可以作为一种改进 - 我只添加了这三种方法,因为你的问题中有这三种类型。让它们都实现一个接口肯定会改进你的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 2022-01-06
  • 2017-09-16
  • 1970-01-01
  • 2015-01-09
相关资源
最近更新 更多