Java开发如何避免instanceof判断和动态getter校验,消除Card类相关冗余代码
方案1:泛型工具方法(无侵入,首选)
三个方法的逻辑完全一致:校验两个Card是否为指定子类的实例,是则提取对应属性比较是否相等。你可以把重复逻辑抽为通用私有泛型方法,原有对外方法保持签名不变,不需要修改任何Card相关类的代码:
import java.util.Objects; import java.util.function.Function; public class CardUtility { // 通用校验逻辑 private static <T extends Card> boolean checkMatch(Card c1, Card c2, Class<T> type, Function<T, ?> propertyGetter) { if (type.isInstance(c1) && type.isInstance(c2)) { T t1 = type.cast(c1); T t2 = type.cast(c2); // 属性为基础类型/枚举可直接换成 == 判断 return Objects.equals(propertyGetter.apply(t1), propertyGetter.apply(t2)); } return false; } // 原有对外方法简化为一行 public static boolean areBothColoredAndHaveSameColor(Card c1, Card c2) { return checkMatch(c1, c2, ColoredCard.class, ColoredCard::getColor); } public static boolean areBothNumberedAndHaveSameNumber(Card c1, Card c2) { return checkMatch(c1, c2, NumberedCard.class, NumberedCard::getNumber); } public static boolean areBothSpecialAndHaveSameSpeciality(Card c1, Card c2) { return checkMatch(c1, c2, SpecialColoredCard.class, SpecialColoredCard::getSpeciality); } }
这个方案完全符合你的限制条件,也不会破坏现有继承结构,还保留了原有的三个方法语义,不会影响现有调用逻辑。
方案2:CardWithKeyProperty接口方案(适用单核心比较属性场景)
你提到的接口方案完全合理,你担心的继承层级问题很好解决:直接让抽象父类ColoredCard实现这个接口即可,子类不需要重复实现,只需要按需重写:
- 定义通用接口
public interface CardWithKeyProperty<T> { T getKeyProperty(); }
- 对应类实现接口
ColoredCard实现接口,默认返回颜色属性:public abstract class ColoredCard extends Card implements CardWithKeyProperty<Color> { @Override public Color getKeyProperty() { return getColor(); } }NumberedCard重写接口方法,返回数字属性:public class NumberedCard extends ColoredCard { @Override public Integer getKeyProperty() { return getNumber(); } }SpecialColoredCard重写接口方法,返回特殊类型属性:public class SpecialColoredCard extends ColoredCard { @Override public Speciality getKeyProperty() { return getSpeciality(); } }
- 封装统一比较方法
public static boolean doBothHaveTheSameKeyProperty(Card c1, Card c2) { // 如需限制必须为同类型,可追加 c1.getClass() == c2.getClass() 校验 if (c1 instanceof CardWithKeyProperty<?> k1 && c2 instanceof CardWithKeyProperty<?> k2) { return Objects.equals(k1.getKeyProperty(), k2.getKeyProperty()); } return false; }
注意:这个方案只适合业务中所有Card子类只有一个核心比较属性的场景,如果你的业务存在多维度比较需求(比如有时需要对比NumberedCard的颜色、有时需要对比数字),就不要用这个方案。
内容的提问来源于stack exchange,提问作者learner
相关产品推荐
相关产品推荐

