多平台通用枚举的面向对象优化设计咨询
多平台通用枚举的面向对象优化设计咨询
你现在遇到的问题很典型——重复的枚举结构严重违反了**DRY(Don't Repeat Yourself)**原则,每次新增云厂商都要复制粘贴大量重复代码,不仅冗余还容易出错,维护成本很高。下面给你两种贴合Java面向对象思想的优化方案,你可以根据实际需求选择:
方案1:组合模式+接口规范(保留枚举特性)
这种方案既能保留枚举的类型安全、常量唯一性、switch支持等特性,又能把公共逻辑完全抽离出来,避免重复代码。
步骤1:定义公共的基础等级类
把所有枚举共用的字段、构造器和getter逻辑放到一个独立类中:
public class BaseRiskLevel { private final String level; private final String levelAuto; private final String levelStr; // 处理两种构造场景:带levelStr和不带的 public BaseRiskLevel(String level, String levelAuto) { this(level, levelAuto, null); } public BaseRiskLevel(String level, String levelAuto, String levelStr) { this.level = level; this.levelAuto = levelAuto; this.levelStr = levelStr; } // 统一的getter方法 public String getLevel() { return level; } public String getLevelAuto() { return levelAuto; } public String getLevelStr() { return levelStr; } }
步骤2:定义接口规范
创建一个接口来统一所有厂商等级枚举的行为,方便后续代码的统一处理:
public interface RiskLevel { String getLevel(); String getLevelAuto(); String getLevelStr(); }
步骤3:改造各厂商枚举
每个厂商的枚举只需要实现RiskLevel接口,持有BaseRiskLevel实例并委托方法即可:
// AWS枚举 public enum LevelsAWS implements RiskLevel { ALERT(new BaseRiskLevel("0.0", "0.0")), HIGH(new BaseRiskLevel("1e-8", "1e-7", "0")), MEDIUM(new BaseRiskLevel("1e-6", "1e-5", "1")), LOW(new BaseRiskLevel("1e-4", "1e-3", "2")); private final BaseRiskLevel baseLevel; LevelsAWS(BaseRiskLevel baseLevel) { this.baseLevel = baseLevel; } // 委托给BaseRiskLevel实现接口方法 @Override public String getLevel() { return baseLevel.getLevel(); } @Override public String getLevelAuto() { return baseLevel.getLevelAuto(); } @Override public String getLevelStr() { return baseLevel.getLevelStr(); } } // Azure枚举(结构完全一致,仅常量值不同) public enum LevelsAZURE implements RiskLevel { ALERT(new BaseRiskLevel("1.0", "1.0")), HIGH(new BaseRiskLevel("1e-160", "1e-175", "0")), MEDIUM(new BaseRiskLevel("1e-110", "1e-125", "1")), LOW(new BaseRiskLevel("1e-12", "1e-15", "2")); private final BaseRiskLevel baseLevel; LevelsAZURE(BaseRiskLevel baseLevel) { this.baseLevel = baseLevel; } @Override public String getLevel() { return baseLevel.getLevel(); } @Override public String getLevelAuto() { return baseLevel.getLevelAuto(); } @Override public String getLevelStr() { return baseLevel.getLevelStr(); } }
优点:完全保留枚举的所有特性,公共逻辑只写一次,后续新增GCP等厂商时,只需要复制枚举结构并替换常量值即可,重复代码极少,维护成本低。
方案2:通用枚举+配置类(更灵活的配置化方案)
如果所有云厂商的等级类型都是固定的ALERT/HIGH/MEDIUM/LOW,可以选择这种方案,把等级类型和具体值分离,用配置类存储不同厂商的参数:
步骤1:定义通用等级类型枚举
public enum RiskLevelType { ALERT, HIGH, MEDIUM, LOW }
步骤2:定义厂商配置类
用配置类来存储每个厂商对应的等级值:
public class ProviderRiskConfig { private final Map<RiskLevelType, BaseRiskLevel> levelMapping; public ProviderRiskConfig(Map<RiskLevelType, BaseRiskLevel> levelMapping) { this.levelMapping = levelMapping; } // 根据类型获取对应等级信息 public BaseRiskLevel getRiskLevel(RiskLevelType type) { return levelMapping.get(type); } }
步骤3:创建各厂商的配置实例
// AWS配置 public class AWSRiskConfig { public static final ProviderRiskConfig INSTANCE = new ProviderRiskConfig(Map.of( RiskLevelType.ALERT, new BaseRiskLevel("0.0", "0.0"), RiskLevelType.HIGH, new BaseRiskLevel("1e-8", "1e-7", "0"), RiskLevelType.MEDIUM, new BaseRiskLevel("1e-6", "1e-5", "1"), RiskLevelType.LOW, new BaseRiskLevel("1e-4", "1e-3", "2") )); } // Azure配置 public class AzureRiskConfig { public static final ProviderRiskConfig INSTANCE = new ProviderRiskConfig(Map.of( RiskLevelType.ALERT, new BaseRiskLevel("1.0", "1.0"), RiskLevelType.HIGH, new BaseRiskLevel("1e-160", "1e-175", "0"), RiskLevelType.MEDIUM, new BaseRiskLevel("1e-110", "1e-125", "1"), RiskLevelType.LOW, new BaseRiskLevel("1e-12", "1e-15", "2") )); }
优点:不需要为每个厂商创建新枚举,新增厂商只需要添加配置类即可,灵活性更高;如果后续需要修改某个厂商的参数,直接修改配置即可,不需要改动枚举代码。
方案选择建议
- 如果你的业务需要严格的枚举类型安全(比如用switch处理不同等级、依赖枚举常量的唯一性),优先选方案1;
- 如果所有厂商的等级类型固定,且更看重配置灵活性和扩展性,选方案2。
备注:内容来源于stack exchange,提问作者Mohit Munjal
相关产品推荐
相关产品推荐

