java - 避免在 Java 中使用带有附加字段的子类的 instanceof

标签 java oop

我最近正在开发一个代码库,该代码库在整个代码中使用了大量的instanceof检查,我想知道是否有更好的方法来重构它。

作为一个例子,有一个 AbstractTender 类,它有几个子类,CreditDebitTender、CheckTender、GiftCardTender、StoreCreditTender 等。每个类都添加了几个字段、方法和自己的逻辑。这导致对整个代码进行检查,如下所示。

考虑到父类(super class)和子类 IE 在某些情况下存在更多且非常不同的字段/方法之间存在显着差异,是否有更好的方法来避免整个代码库中的所有 instanceof 检查?正如示例 maskedCardNumber 和 authCode 仅特定于贷记借记投标,而 micr 仅特定于支票投标。

if (tender instanceof CreditDebitTenderIfc) {
    // insert tender into credit debit tender table
}

if (tender instanceof CheckTenderIfc) {
    // insert tender into check tender table
}

if (tender instance of GiftCardTenderIfc) {
    // inser tender into gift card tender table
}

// etc

仅供引用:这是一个非常古老的代码库,原始产品已经有 10 多年的历史了。

最佳答案

我可以考虑两种方法:

  1. AbstractTender中定义一个抽象方法叫save 。每个子类都必须实现如何将信息存储在数据库中。

  2. 如果 AbstractTender子类是实体类,不能有存储库逻辑,如果您使用Java 8,则可以使用 Map<Class, Consumer<AbstractTender>>其中map的每个值重点关注如何存储AbstractTender的实例。您可以使用实例的类来查找特定元素。

    简单示例:

    Map<Class, Consumer<AbstractTender>> mapTenderStoreFunc = new HashMap<>();
    mapTenderStoreFunc.put(CreditDebitTenderIfc.class, tender -> {
            CreditDebitTenderIfc cdTender = (CreditDebitTenderIfc)tender;
            //logic goes here...
        });
    mapTenderStoreFunc.put(CheckTenderIfc.class, tender -> {
            CheckTenderIfccdTender ctifc = (CheckTenderIfc)tender;
            //logic goes here...
        });
    //and on...
    

    然后你的save方法将像这样使用 map :

    public void save(AbstractTender tender) {
        Consumer<AbstractTender> saveOperation = mapTenderStoreFunc.get(tender.getClass());
        if (saveOperation != null) {
            saveOperation.accept(tender);
        } else {
            //maybe throw an exception
            //or log a warning, error or something to notice!
        }
    }
    

    这种方法的缺点是,如果团队中有人忘记为子类添加正确的映射,那么您就会遇到麻烦。

  3. 与 2 类似的方法,但如果您使用 Java 7 或更早版本,而不是 Consumer<AbstractTender>您可以定义自己的接口(interface)并用匿名类填充它:

    interface TenderRepository {
        void save(AbstractTender tender);
    }
    
    Map<Class, TenderRepository> map = new HashMap<>();
    map.put(CreditDebitTenderIfc.class, new TenderRepository() {
            @Override
            public void save(AbstractTender tender) {
                CreditDebitTenderIfc cdTender = (CreditDebitTenderIfc)tender;
                //logic goes here...
            }
        });
    

关于java - 避免在 Java 中使用带有附加字段的子类的 instanceof,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48472178/

相关文章:

java - (SPRING) 从 postgresql 数据库获取用户信息并在 thymeleaf html 中打印

java - 在 Spring MVC 中显示带有复选框的列表

java - 无法理解使用 for 循环的部分代码?

java - Maven 无法检测到我的 Node 安装

java - 仅比较两个实例之间的一个变量

java - 更新实例变量值并确保私有(private)方法使用它们 - Java

JavaScript 原型(prototype)与实践中的 this

java - 扩展两个类

language-agnostic - 对接口(interface)编程,通用性有多通用?

java - 下载没有缓冲区的文件: Nio is faster than io?