【问题标题】:Using instanceof operarator for deserialization使用 instanceof 操作符进行反序列化
【发布时间】:2023-03-19 18:30:01
【问题描述】:

我遇到过不同的帖子,其中说使用 instanceof 不是一种好的做法。

http://www.javapractices.com/topic/TopicAction.do?Id=31 https://www.artima.com/interfacedesign/PreferPoly.html

我的情况是,我有一个序列化对象,它可以是 7,8 种实际类型。现在我正在使用insntanceof 运算符并使用各种 if 条件检查对象是否为实际类型,然后进行一些操作。

我的设计不好吗?

如果是这样,我如何在不使用instanceof 的情况下解决此问题?

每个对象的继承层次都不同,所以我很难用多态来替换它。

代码

 public String exportAsPMML(MLModel model) throws MLModelHandlerException {
        Externalizable extModel = model.getModel();

        //Deserializing to find the actual type of the model
        if (extModel instanceof MLClassificationModel) {
            ClassificationModel clasModel = ((MLClassificationModel) extModel).getModel();
            if (clasModel instanceof LogisticRegressionModel) {
                return ((LogisticRegressionModel) clasModel).toPMML();
            } else {
                throw new MLModelHandlerException("PMML export not supported for model type");
            }
        } else if (extModel instanceof MLGeneralizedLinearModel) {
            GeneralizedLinearModel genModel = ((MLGeneralizedLinearModel) extModel).getModel();
            if (genModel instanceof LinearRegressionModel) {
                return ((LinearRegressionModel) genModel).toPMML();
            } else if (genModel instanceof LassoModel) {
                return ((LassoModel) genModel).toPMML();
            } else if (genModel instanceof RidgeRegressionModel) {
                return ((RidgeRegressionModel) genModel).toPMML();
            } else {
                throw new MLModelHandlerException("PMML export not supported for model type");
            }
        } else if (extModel instanceof MLKMeansModel) {
            KMeansModel kmeansModel = ((MLKMeansModel) extModel).getModel();
            return kmeansModel.toPMML();
        } else {
            throw new MLModelHandlerException("PMML export not supported for model type");
        }
    }

【问题讨论】:

  • 你能把你的代码贴在你用过instanceof的地方吗?
  • 您可以将类型存储为成员
  • 没有实际代码很难得到清晰的图片。但根据您的设计,instanceof 可能是一个有效的解决方案。您也可以使用泛型进行设计
  • 我已添加代码
  • 这需要基类/通用接口。

标签: java instanceof


【解决方案1】:

使用现有接口PMMLExportable

GeneralizedLinearModel genModel = ((MLGeneralizedLinearModel) extModel).getModel();
if (genModel instanceof PMMLExportable) {
    return ((PMMLExportable) genModel).toPMML();
} else {
    throw new MLModelHandlerException("PMML export not supported for model type");
}

然后添加你自己的接口来得到这个:

public interface PpmlModelContainer{
    PMMLExportable getPMMLExportable();
}

 public String exportAsPMML(MLModel model) throws MLModelHandlerException {
    Externalizable extModel = model.getModel();

    if (extModel instanceof PpmlModelContainer) {
        PMMLExportable ppmlModel = ((PpmlModelContainer) extModel).getPMMLExportable();
        return ppmlModel.toPMML();
    } else {
        throw new MLModelHandlerException("PMML export not supported for model type");
    }
}

什么需要实现什么:

MLClassificationModel implements PpmlModelContainer
MLGeneralizedLinearModel implements PpmlModelContainer
MLKMeansModel implements PpmlModelContainer

系统现在是open closed。对扩展开放,对修改关闭。

【讨论】:

  • 但是 kmeansModel 和 LogisticRegressionModel 没有扩展 GeneralizedLinearModel
  • 好的,我添加了一个界面选项并将其扩展到您的整个问题。
  • 问题是 LogisticRegressionModel、LinearRegressionModel 等来自 spark MLlib,我必须在不修改 spark 内部结构的情况下实现这一点
  • 已经有接口可以使用:PMMLExportable!
【解决方案2】:

虽然使用instanceof 被认为是代码异味,但情况并非总是如此。如果您在做任何事情之前肯定需要知道对象的类型,那么instanceof 是一个不错的选择。

但是拥有大量它们并根据类型调用单独的方法(使用强制转换)并不是一个好的选择。在这种情况下,我们需要重新考虑层次结构和可能的重构。

在您的情况下,您似乎可以拥有一个具有方法 toPMML 的基本接口,该方法可以由所有具体类实现。这其实就是我们所说的Program to interface

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 2016-03-29
    • 2021-12-13
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多