【问题标题】:java inheritance vs genericsjava继承与泛型
【发布时间】:2016-07-21 17:27:34
【问题描述】:

这里有一点 Java 设计问题(重要的是它在 JEE Web 应用程序的上下文中)。

假设我有一个带有两个操作的 REST API:GETPOST 在相同的资源上。从那里,使用 Jackson 构造两个类来表示请求的输入字段。这些类是不同的,因为请求的参数略有不同。

假设这两个类被命名为 GetRequestPostRequest

这两个类包含一组通用字段。以及属于每个类的一组字段。例如:

public class GetRequest {

   // common fields
   private String callerId;

   private String userId;

   // non-common fields
   private boolean withLinkedServices;

   // Constructors, egals, hasCode, toString, getters,setter etc...
}

对于 PostRequest 类

public class PostRequest {

   // common fields
   private String callerId;

   private String userId;

   // non-common fields
   private List<ServicesBean> services;

   // Constructors, egals, hasCode, toString, getters,setter etc...
}

在我的应用程序的业务层中,我必须编写一个 helper 方法(针对每个 REST 操作),该方法将使用每个对象的公共字段填充另一个 bean。对于 GET 和 POST 操作,此方法的实现完全相同。

唯一不同的是,对于 GET 操作,我必须通过 GetRequest 类,而对于 POST,我必须通过 PostRequest

所以我的问题是:

我应该使用数据模型并使用继承还是应该在我的辅助方法中使用泛型?哪一个更有意义、更高效、更能适应应用程序的未来发展(例如,如果在该资源上添加更多操作)?

我的方法的签名是(对于 POST 的助手):

public IDaoRequestBean buildDaoRequest(final PostRequest request);

对于 GET 的助手:

public IDaoRequestBean buildDaoRequest(final GetRequest request);

【问题讨论】:

标签: java generics inheritance


【解决方案1】:

实际上并不需要使用泛型。您需要让两个类都实现一个通用接口,因此您可以调用getCallerID/getUserID。但是让它们都实现一个通用接口,就不需要泛型了:

interface IRequest {
    String getCallerID();
    String getUserID();
}
/* Overcomplicated, with generics */
public <T extends IRequest> IDaoRequestBean buildDaoRequest(final T){...}

/* Using just the interface */
public IDaoRequestBean buildDaoRequest(final IRequest){...}

所以你很坚持继承。


使用abstract class 代替接口还有一个额外的好处,那就是不必重新声明字段和getter。限制你不能扩展任何其他类。

abstract class BaseRequest {
    private String callerId;
    private String userId;

    // Getters
}

class GetRequest extends BaseRequest {...}
class PostRequest extends BaseRequest {...}
/* Pretty much the same here... */
public IDaoRequestBean buildDaoRequest(final BaseRequest){...}

【讨论】:

    【解决方案2】:

    在我看来,您不应该将 GetRequest 作为 get 方法调用的请求主体。 get rest 调用应基于 Id(例如:employees/id)。 由于某些原因,如果您在请求正文中有一个对象,请遵循类层次结构中的继承,但在其余方法和辅助方法实现方法中具体说明您的类类型,因为

    1. 将来,您可能需要添加一个新的通用属性,以便此模型为您提供灵活性。

      抽象类 AbstractRequest{ //常用属性 }

      类 GetRequest 扩展 AbstractRequest{}

      类 PostRequest 扩展 AbstractRequest{}

    2. 同样在其余模型参数和辅助类方法参数中,如果您没有将特定的子类型定义为参数,其他开发人员可以使用参数的任何子类型调用您的辅助类。这可能会破坏您的功能。所以要具体说明 helper 和 rest 方法中的参数类型。

      GET -> 方法(GetRequest)

      POST -> 方法(PostRequest)

      public IDaoRequestBean buildDaoRequest(最终的 PostRequest 请求);

      public IDaoRequestBean buildDaoRequest(最终的GetRequest请求);

    【讨论】:

      【解决方案3】:

      我相信继承是要走的路。如果你最终有新的请求,拥有泛型可能意味着你可以传递一种可能与方法的实现不匹配的请求类型,除非它们扩展同一个类,这会导致继承,不是吗?通过仅具有 POST 和 GET 的超类类型的请求,您将其限制为它们两者。如果我错了,请纠正我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-06
        • 2021-10-11
        • 1970-01-01
        • 2011-04-25
        • 1970-01-01
        相关资源
        最近更新 更多