【问题标题】:Invoke concrete class functions through common interface通过通用接口调用具体的类函数
【发布时间】:2018-03-14 17:56:26
【问题描述】:

我有以下实现通用接口的具体类

EvaluatorA : IEvaluator
EvaluatorB : IEvaluator
EvaluatorC : IEvaluator

接口IEvaluator只有一个功能——Evaluate,它在所有三种类型的求值器中都实现了。而且我有一个驱动程序类,它根据配置调用评估器,但是,它只能(通过设计)访问IEvalutor,即,它不需要知道当前正在调用哪个具体的评估器。

当其中一位评估者,比如说EvaluatorC,需要实现一个新函数Predict,而我的要求只针对EvaluatorCPredict函数需要在调用@987654329之后调用@。

临时解决方案 1: 一种解决方案是检查评估器类型:

// evaluator is previously instanciated
evaluator.Evaluate();
if (evaluator is EvaluatorC)
    evaluator.Predict();

如您所见,这并不整洁。假设明天我需要为 EvaluatorB 调用另一个函数 Dance 并为 EvaluatorAEvaluatorB 调用函数 Sing,它变得混乱。

时间解2: 将函数Predict添加到接口IEvaluator中,对于其他的求值者,只需用空体实现函数即可。这可能适用于void 返回类型的函数,但如果返回类型不是void,则需要在驱动程序中进行额外的安全检查。此外,我不确定将空体仅作为占位符的函数是否是一个好主意。

临时解决方案 3: 将接口更改为抽象类。这类似于解决方案 2,但提供了Predict 的默认实现。但是,我也不喜欢这种方法,因为它改变了项目的原始结构,并且与解决方案 2 相比并没有带来太多好处。

总的来说,我对这个问题没有满意的解决方案。我希望decoration pattern 可以提供帮助(但我不确定)。此问题并非特定于任何编程语言。请加入并分享您的想法。

编辑 1:添加了有关评估员职责的一些详细信息 评估者应该评估给定的解决方案并返回一些指标。得到评估指标后,驱动程序会做一些家务,比如报告,注意这是所有评估者都需要的。然后其中一位评估者 (EvaluatorC) 需要根据生成的报告调用 Predict()。但是,其他评估者不需要此步骤。

【问题讨论】:

  • 为什么不在EvaluatorCEvaluate方法中调用Predict
  • @sdgfsdh,好点子。最初的计划是这样,但是在调用Evaluate()之后发现驱动程序中需要做一些内务工作。之后才能调用Predict()
  • 那么驱动程序是否也在Evaluate方法中工作?您似乎还没有为您的问题找到合适的抽象。
  • 在不知道 EvaluatePredict 实际在做什么的情况下很难提供帮助。听起来Predict 对于Evaluator 来说并不常见,所以它不应该在那个类中。您可以将它移动到另一个类Predictor,在调用evaluate 之后,您将在driver 类中使用该类。 Predictor 可以接收来自Evaluator 的响应并执行其操作。

标签: design-patterns interface abstract-class decorator object-oriented-analysis


【解决方案1】:

既然我们谈论的是设计模式,我认为您所描述的内容让我想起了template method pattern

本质是在基类中定义算法的骨架,让子类选择是否要实现某些步骤。这是一个例子。

abstract class EvaluatorPredictor {
  void evaluateAndPredict() {
    evaluate();
    predict();
  }

  protected void evaluate() {
    // no-op
  };

  protected void predict() {
    // no-op
  };
}

class AEvaluator extends EvaluatorPredictor {
  protected void evaluate() {
    System.out.println("I implement this");
  }
}

class BEvaluator extends EvaluatorPredictor {
  protected void evaluate() {
    System.out.println("I implement this");
  }


  protected void predict() {
    System.out.println("I implement this too");
  }
}

请注意,您可以通过组合获得更多力量。例如,EvaluatorPredictor 或任何与此相关的类都可以使用两个分别实现 EvaluatorPredictor 接口的对象。

class Whatever {
  constructor(e Evaluator, p Predictor) {
    this.e = e;
    this.p = p;
  }

  void evaluateAndPredict() {
    this.e.evaluate();
    this.p.predict();
  }
}

PS。请原谅我糟糕的类似 Java 的语法。我确定方法声明或访问修饰符中有错误。希望以上内容有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-18
    • 2019-01-05
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 2020-01-20
    相关资源
    最近更新 更多