java - 当派生类主要用于扩展状态而不是行为时,如何动态获取继承层次结构中的子类?

标签 java oop inheritance design-patterns instanceof

我正在尝试使用 Jumblr 来使用我的 tumblr 数据这是一个 Java 的 Tumblr API 包装客户端。

我研究了源代码,发现由于 Json 响应是动态的,所以有一个 Post POJO 和派生的 POJO,如 TextPost、QuotePost、PhotoPost 等来反序列化为 pojo。它通过使用 Gson 和使用反射的自定义反序列化器以通用方式处理消费。例如,它通过这种方式反序列化对 TextPost 的 Json 响应并将其分配给 Post 对象。

因此,为了获取子类的字段,我需要在 instanceof 检查后向下转换 Post 对象,如下所示:

List<Post> posts =  blog.draftPosts();
Post post = posts.get(0); //gets a TextPost
if(post instanceof TextPost) {
    System.out.println("title: " + ((TextPost) post).getTitle());
    System.out.println("body: " + ((TextPost) post).getBody()); 
}
else if(post instanceof QuotePost) {
    //...
}
else if...

我不确定这是最好的方法。所以我正在从面向对象编程概念(如多态性或其他)的角度寻找更优雅或最好的方法或正确的方法。

获取子类或从父类(super class)访问子类的正确方法是什么?

您如何评估 API 的面向对象设计,该设计通过扩展包含额外状态的特定类来使用继承?这是一种合理的方法吗?从客户的角度来看,还有哪些其他方法可以处理响应?既然不是行为继承,那么使用继承只继承状态是否正确?

来自 API 来源:


public class Post {
    protected PostType type;
    private Long id;
    private String author;
    private String reblog_key;
    private String blog_name;
    //more state and getters/setters
}

public class TextPost extends Post {
    //extra fields
    private String title;
    private String body;

    //getters/setters
}


public List<Post> getPosts() {
    Gson gson = gsonParser();
    JsonObject object = (JsonObject) response;
    List<Post> l = gson.fromJson(object.get("posts"), new 
                        TypeToken<List<Post>>() {}.getType());
    ...
}

private Gson gsonParser() {
        return new GsonBuilder().
            registerTypeAdapter(Post.class, new PostDeserializer()).
            create();
    }

public class PostDeserializer implements JsonDeserializer<Object> {

    @Override
    public Object deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
        JsonObject jobject = je.getAsJsonObject();
        String typeName = jobject.get("type").getAsString();
        String className = typeName.substring(0, 1).toUpperCase() + typeName.substring(1) + "Post";
        try {
            Class<?> clz = Class.forName("com.tumblr.jumblr.types." + className);
            return jdc.deserialize(je, clz);
....

}

最佳答案

首先:没有“正确”的做法,只有优雅和不优雅的做法。处理此类问题的常见模式是以下之一:

  1. 让不同的类根据对象的子类决定如何处理(就像您在示例中所做的那样)。
  2. 通过抽象基类的(抽象)方法将处理子类状态的责任转移到子类中,每个子类都必须以自己的方式实现该方法。
  3. 将处理子类状态的责任移交给访问者 ( https://en.wikipedia.org/wiki/Visitor_pattern ),每个子类都会“访问”该访问者,并根据调用对象的类型来实现行为。

关于java - 当派生类主要用于扩展状态而不是行为时,如何动态获取继承层次结构中的子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57180689/

相关文章:

java - 按下鼠标时如何绘制蓝色矩形?

c++ - 调用成员函数时遇到问题

java - 确定面向对象类中的方法依赖性

c# - 如何从抽象父类(super class)中引用子类的字段?

Javascript 简单原型(prototype)继承

java - 将 UTC 时间戳转换为其他时区特定时间

java 和 libGDX/LWJGL 游戏全屏尺寸错误,适用于 Ubuntu 上的多个显示器

java - 如何使用 Apache Camel 定期处理一些输入

c++ - 如何在 C++ 中转换类型?

c++ - 这种语法合法吗?