Java 从方法中的父类动态转换为适当的子类

Java 从方法中的父类动态转换为适当的子类,java,generics,lambda,java-8,Java,Generics,Lambda,Java 8,我有一个Java接口平台。我还有两个类PlatformProducerConfig和PlatformConsumerConfig 稍后,我需要为这两个文件添加一个公共配置,将属性设置为空字符串: private PlatformConfigurable disableHostNameVerificationConfig(PlatformConfigurable platformConfig) { if (platformConfig instanceof Platform

我有一个Java接口平台。我还有两个类PlatformProducerConfig和PlatformConsumerConfig

稍后,我需要为这两个文件添加一个公共配置,将属性设置为空字符串:

    private PlatformConfigurable disableHostNameVerificationConfig(PlatformConfigurable platformConfig) {
        if (platformConfig instanceof PlatformProducerConfig) {
            PlatformProducerConfig oldConfig = (PlatformProducerConfig) platformConfig;
            Map<String, String> additionalConfig = oldConfig.additionalProperties();
            Map<String, String> newConfig = new HashMap<>(Optional.ofNullable(additionalConfig).orElseGet(ImmutableMap::of));
            newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");
            return oldConfig.toBuilder().additionalProperties(newConfig).build();
        }
        else if (platformConfig instanceof PlatformConsumerConfig) {
            PlatformConsumerConfig oldConfig = (PlatformConsumerConfig) platformConfig;
            Map<String, String> additionalConfig = platformConfig.additionalProperties();
            Map<String, String> newConfig = new HashMap<>(Optional.ofNullable(additionalConfig).orElseGet(ImmutableMap::of));
            newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");
            return oldConfig.toBuilder().additionalProperties(newConfig).build();
        }
        return platformConfig;
    }

我曾考虑过使用lambdas,但我不能100%确定如何使用它。

您可以像这样重构现有代码:

private PlatfromConfigurable disableHostNameVerificationConfig(Platfromonfigurable platfromConfig) {
    if (!(platformConfig instanceof PlatformProducerConfig) && !(platformConfig instanceof PlatformConsumerConfig)) {
        return platformConfig;
    }

    Map<String, String> additionalConfig = platformConfig.additionalProperties();
    Map<String, String> newConfig = new HashMap<>(Optional.ofNullable(additionalConfig).orElseGet(ImmutableMap::of));
    newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");

    if (platformConfig instanceof PlatformProducerConfig) {
        return ((PlatformProducerConfig)platformConfig).toBuilder().additionalProperties(newConfig).build();
    }
    return ((PlatformConsumerConfig)platformConfig).toBuilder().additionalProperties(newConfig).build();
}
更新

另一种方法是提取与构建器相关的功能以分离接口,并以这种方式使用它们:

// 1. extend existing `PlatformConfigurable`
public interface BuilderedPlatformConfigurable extends PlatformConfigurable {
    ConfigPlatformBuilder toBuilder();
}

// 2. provide builder interface with common implementation
public interface ConfigPlatformBuilder {
    Map<String, String> additionalProperties = new HashMap<>();

    BuilderedPlatformConfigurable build();

    default ConfigPlatformBuilder additionalProperties(Map<String, String> properties) {
        this.additionalProperties.clear();
        this.additionalProperties.putAll(properties);
        return this;
    }
}

// 3. update PlatformConsumerConfig class (similarly, PlatformProducerConfig)
public class PlatformConsumerConfig implements BuilderedPlatformConfigurable {
    private Map<String, String> additionalProperties = new HashMap<>();

    @Override
    public Map<String, String> additionalProperties() {
        return additionalProperties;
    }

    public ConfigPlatformBuilder toBuilder() {
        return new Builder();
    }

    public static class Builder implements ConfigPlatformBuilder {
        public PlatformConsumerConfig build() {
            PlatformConsumerConfig config = new PlatformConsumerConfig();
            config.additionalPropertie.putAll(this.additionalProperties);
            return config;
        }
    }
}

// 4. provide overloaded method
private PlatformConfigurable disableHostNameVerificationConfig(PlatformConfigurable platformConfig) {
    return platformConfig;
}

private PlatformConfigurable disableHostNameVerificationConfig(BuilderedPlatformConfigurable platformConfig) {
    Map<String, String> additionalConfig = platformConfig.additionalProperties();
    Map<String, String> newConfig = new HashMap<>(Optional.ofNullable(additionalConfig).orElseGet(Map::of));
    newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");

    return platformConfig.toBuilder().additionalProperties(newConfig).build();
}


您可以像这样重构现有代码:

private PlatfromConfigurable disableHostNameVerificationConfig(Platfromonfigurable platfromConfig) {
    if (!(platformConfig instanceof PlatformProducerConfig) && !(platformConfig instanceof PlatformConsumerConfig)) {
        return platformConfig;
    }

    Map<String, String> additionalConfig = platformConfig.additionalProperties();
    Map<String, String> newConfig = new HashMap<>(Optional.ofNullable(additionalConfig).orElseGet(ImmutableMap::of));
    newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");

    if (platformConfig instanceof PlatformProducerConfig) {
        return ((PlatformProducerConfig)platformConfig).toBuilder().additionalProperties(newConfig).build();
    }
    return ((PlatformConsumerConfig)platformConfig).toBuilder().additionalProperties(newConfig).build();
}
更新

另一种方法是提取与构建器相关的功能以分离接口,并以这种方式使用它们:

// 1. extend existing `PlatformConfigurable`
public interface BuilderedPlatformConfigurable extends PlatformConfigurable {
    ConfigPlatformBuilder toBuilder();
}

// 2. provide builder interface with common implementation
public interface ConfigPlatformBuilder {
    Map<String, String> additionalProperties = new HashMap<>();

    BuilderedPlatformConfigurable build();

    default ConfigPlatformBuilder additionalProperties(Map<String, String> properties) {
        this.additionalProperties.clear();
        this.additionalProperties.putAll(properties);
        return this;
    }
}

// 3. update PlatformConsumerConfig class (similarly, PlatformProducerConfig)
public class PlatformConsumerConfig implements BuilderedPlatformConfigurable {
    private Map<String, String> additionalProperties = new HashMap<>();

    @Override
    public Map<String, String> additionalProperties() {
        return additionalProperties;
    }

    public ConfigPlatformBuilder toBuilder() {
        return new Builder();
    }

    public static class Builder implements ConfigPlatformBuilder {
        public PlatformConsumerConfig build() {
            PlatformConsumerConfig config = new PlatformConsumerConfig();
            config.additionalPropertie.putAll(this.additionalProperties);
            return config;
        }
    }
}

// 4. provide overloaded method
private PlatformConfigurable disableHostNameVerificationConfig(PlatformConfigurable platformConfig) {
    return platformConfig;
}

private PlatformConfigurable disableHostNameVerificationConfig(BuilderedPlatformConfigurable platformConfig) {
    Map<String, String> additionalConfig = platformConfig.additionalProperties();
    Map<String, String> newConfig = new HashMap<>(Optional.ofNullable(additionalConfig).orElseGet(Map::of));
    newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");

    return platformConfig.toBuilder().additionalProperties(newConfig).build();
}

再进一步,使用泛型:

private <P extends PlatformConfigurable> P disableHostNameVerificationConfig(P platformConfig, BiFunction<P, Map<String, String>, P> appender) {
    Map<String, String> additionalConfig = platformConfig.additionalProperties();
    Map<String, String> newConfig = new HashMap<>(Optional.ofNullable(additionalConfig).orElseGet(ImmutableMap::of));
    newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");

    return appender.apply(platformConfig, newConfig);
}
如果愿意,请创建帮助器方法以隐藏双功能:

实际上,我认为更好的方法是不使用泛型或lambda:编写一个创建更新映射的方法:

private static Map<String, String> newConfig(PlatformConfigurable platformConfig) {
  Map<String, String> additionalConfig = platformConfig.additionalProperties();
  Map<String, String> newConfig = additionalConfig != null ? new HashMap<>(additionalConfig) : new HashMap<>();

  newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");
  return newConfig;
}
再进一步,使用泛型:

private <P extends PlatformConfigurable> P disableHostNameVerificationConfig(P platformConfig, BiFunction<P, Map<String, String>, P> appender) {
    Map<String, String> additionalConfig = platformConfig.additionalProperties();
    Map<String, String> newConfig = new HashMap<>(Optional.ofNullable(additionalConfig).orElseGet(ImmutableMap::of));
    newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");

    return appender.apply(platformConfig, newConfig);
}
如果愿意,请创建帮助器方法以隐藏双功能:

实际上,我认为更好的方法是不使用泛型或lambda:编写一个创建更新映射的方法:

private static Map<String, String> newConfig(PlatformConfigurable platformConfig) {
  Map<String, String> additionalConfig = platformConfig.additionalProperties();
  Map<String, String> newConfig = additionalConfig != null ? new HashMap<>(additionalConfig) : new HashMap<>();

  newConfig.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "");
  return newConfig;
}

在Alex Rudenko的回答中添加了一件事,并使用不同的函数添加不同的接口实现

私有平台可配置禁用主机名验证配置平台可配置平台配置{ 如果platformConfig==null{ 返回平台配置; } Map additionalConfig=platformConfig.additionalProperties; Map newConfig=new HashMapOptional.OfNullableAddationConfig.orElseGetImmutableMap::of; newConfig.putSslConfigs.SSL_端点_标识_算法_配置; 返回PlatformConfigurableObjectplatformConfig,newConfig; } 因此,您可以在不同的方法中处理所有实例,并且无论以后何时添加PlatfromXCofing类,您只需更改此方法。单一责任原则

私有平台可配置平台可配置平台可配置对象平台可配置平台配置,映射新配置{ 如果platformConfig实例为PlatformProducerConfig{ 返回PlatformProducerConfigplatformConfig.toBuilder.additionalPropertiesnewConfig.build; }否则如果PlatformConsumerConfig的platformConfig实例{ 返回PlatformConsumerConfigplatformConfig.toBuilder.additionalPropertiesnewConfig.build; }否则{ 返回平台配置; } }
在Alex Rudenko的回答中添加了一件事,并使用不同的函数添加不同的接口实现

私有平台可配置禁用主机名验证配置平台可配置平台配置{ 如果platformConfig==null{ 返回平台配置; } Map additionalConfig=platformConfig.additionalProperties; Map newConfig=new HashMapOptional.OfNullableAddationConfig.orElseGetImmutableMap::of; newConfig.putSslConfigs.SSL_端点_标识_算法_配置; 返回PlatformConfigurableObjectplatformConfig,newConfig; } 因此,您可以在不同的方法中处理所有实例,并且无论以后何时添加PlatfromXCofing类,您只需更改此方法。单一责任原则

私有平台可配置平台可配置平台可配置对象平台可配置平台配置,映射新配置{ 如果platformConfig实例为PlatformProducerConfig{ 返回PlatformProducerConfigplatformConfig.toBuilder.additionalPropertiesnewConfig.build; }否则如果PlatformConsumerConfig的platformConfig实例{ 返回PlatformConsumerConfigplatformConfig.toBuilder.additionalPropertiesnewConfig.build; }否则{ 返回平台配置; } }
如果以后添加额外的PlatfromXCofing类呢?如果他们的数量变得相当大怎么办?有没有办法使方法更通用?这是一个很好的重构,但是@Andy Turner给出了一个更一般的答案。非常感谢。我提供了分离构建实现的更新版本:如果以后添加额外的PlatfromXCofing类会怎么样?如果他们的数量变得相当大怎么办?有没有办法使方法更通用?这是一个很好的重构,但是@Andy Turner给出了一个更一般的答案。非常感谢。我提供了分离构建实现的更新版本:这导致:无法解析'P'@QuirkyBit中的方法'toBuilder'。如果您显示问题中类的相关声明,这将有所帮助。PlatformConfigurable上不存在toBuilder方法这一点并不明显。这是在问题描述中:我正在转换到producer或consumer配置,因为PlatfromConfigurable接口没有.toBuilder或.build方法,我没有修改接口的权限,因为我只能实现它。是的,就是这样!非常感谢你!这导致:无法在'P'@QuirkyBit中解析方法'toBuilder'。如果您显示
你问题中的课程。PlatformConfigurable上不存在toBuilder方法这一点并不明显。这是在问题描述中:我正在转换到producer或consumer配置,因为PlatfromConfigurable接口没有.toBuilder或.build方法,我没有修改接口的权限,因为我只能实现它。是的,就是这样!非常感谢你!这是一个很好的重构,但是@Andy Turner给出了一个更一般的答案。非常感谢。这是一个很好的重构,但是@Andy Turner给出了一个更一般的答案。非常感谢。