Java接口(interface)——防止代码重复

标签 java interface wildcard repeat extends

我正在尝试为一组类创建一个接口(interface), 但我未能找到解决方案, 防止为每个新方法复制几乎相似的代码 界面。

界面

public interface P6BO<T extends BusinessObject> {
    String[] getFields();

    void create(T businessObject) throws P6BOException;
    void delete(T businessObject) throws P6BOException;
}

30 多种接口(interface)实现。

public class ActivityBO implements P6BO<Activity> {
    ...

    @Override
    public void create(Activity activity) throws P6BOException {
        ...
    }

    @Override
    public void delete(Activity activity) throws P6BOException {
        ...
    }
}

初始化所有实现的容器类 为每个项目提供单一访问点。

public class P6Bom {
    public final ActivityBO activity = new ActivityBO();
    public final EpsBO eps = new EpsBO();
    public final ResourceBO resource = new ResourceBO();

    public P6Bom(P6Info p6Info) throws P6BOException {
        activity.activate(p6Info, p6Cache, p6Buffer);
        eps.activate(p6Info, p6Cache, p6Buffer);
        resource.activate(p6Info, p6Cache, p6Buffer);
    }

    ...

    public void create(BusinessObject businessObject) throws P6BOException {
        if (businessObject instanceof Activity) {
            activity.create((Activity) businessObject);
        } else if (businessObject instanceof EPS) {
            eps.create((EPS) businessObject);
        } else if (businessObject instanceof Resource) {
            resource.create((Resource) businessObject);
        }
    }

    public void delete(BusinessObject businessObject) throws P6BOException {
        if (businessObject instanceof Activity) {
            activity.delete((Activity) businessObject);
        } else if (businessObject instanceof EPS) {
            eps.delete((EPS) businessObject);
        } else if (businessObject instanceof Resource) {
            resource.delete((Resource) businessObject);
        }
    }

    public P6BO<? extends BusinessObject> getBO(BusinessObject businessObject) throws P6BOException {
        if (businessObject instanceof Activity) {
            return activity;
        } else if (businessObject instanceof EPS) {
            return eps;
        } else if (businessObject instanceof Resource) {
            return resource;
        } else {
            throw new P6BOException("not implemented.");
        }
    }
}

测试类

public class Test() {
    /* Works: but is not generic (I cannot call the delete method for any BusinessObject). */
    Activity activity = new Activity("MyNewActivity");
    P6Bom.activity.create(activity);
    P6Bom.activity.delete(activity);

    /* Works: but results in a double administration in the P6Bom */
    Activity activity = new Activity("MyNewActivity");
    P6Bom.create(activity);
    P6Bom.delete(activity);

    /* Compiler error
       The method delete(capture#1-of ? extends BusinessObject)
       in the type P6BO<capture#1-of ? extends BusinessObject>
       is not applicable for the arguments (Activity)
    */

    p6Bom.getBO(activity).delete(activity);
}

有什么优雅的解决方案可以防止 P6Bom 接口(interface)中每种方法的重复管理?

最佳答案

您可以使用 map :

public class P6Bom {
    public final Map<Class<? extends P6BO<? extends BusinessObject>>, P6BO<? extends BusinessObject>>> classMap;

    public P6Bom(P6Info p6Info) throws P6BOException {
        classMap = new HashMap<>();
        classMap.put(ActivityBo.class, new ActivityBO());
        ...
        for(var bo: classMap.values()) {
         bo.activate(p6Info, p6Cache, p6Buffer);
        }
    }

    ...

    public void create(BusinessObject businessObject) throws P6BOException {
        getBO(businessObject).create(businessObject);
    }

    public P6BO<? extends BusinessObject> getBO(BusinessObject businessObject) throws P6BOException {
        if (classMap.containsKey(businessObject.getClass())) {
            return classMap.get(businessObject.getClass());
        } else {
            throw new P6BOException("not implemented.");
        }
    }
}

我忘记了 <? extends BusinessObject>允许你这样做。如果编译器提示,请忽略 classMap 声明和 getBO 签名中的该部分并忽略警告;-)

这里要记住的是,在字节码中,泛型被删除,因此实际的方法签名允许您始终传入 BusinessObjects。一旦进入方法,如果类不匹配,它将被强制转换并抛出 RuntimeException,但从编译器/接口(interface)方面来看,完全有可能编写这样的代码。

关于Java接口(interface)——防止代码重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61907913/

相关文章:

java - 如何摆脱 tomcat 默认 session ID?

java - Jsoup 获取通用文本

java - IntelliJ IDEA : how to debug a java:fx maven project?

java - 在 Java 中从毛毛虫到蝴蝶的模型

戈朗 : How to change struct field value in slice of interfaces

bash - 如何在bash中捕获和修改正则表达式识别的数字

php - PHP 中的通配符查询在 SQL 中呈现,而不是在 PHP 中呈现

java - 我在 android 5.0.2 源中找到 WIFI_SCANNING_SERVICE 但无法使用此服务

c# - 如何在深度调用中使用 serilog 跟踪请求

java - 使用通配符泛型实现compareTo