使用相同的getter来推广第三方类而不使用反射

时间:2016-11-17 10:12:21

标签: java generics java-8

以下是示例代码:

class A {
    private Header header;
    private Data data;
}

class B {
    private Header header;
    private Data data;
}

class C {
    private Header header;
    private Data data;
}


class G {
    private Class messageType;
    private Header header;
    private Data data;

    public G(Object message) {
        messageType = message.getClass();   
        if (message instanceof A) {
            header = ((A) message).getHeader();
            data = ((A) message).getData();
        } else if (message instanceof B) {
            header = ((B) message).getHeader();
            data = ((B) message).getData();
        } else if (message instanceof C) {
            header = ((C) message).getHeader();
            data = ((C) message).getData();
        }
    }
}

模型类ABC无法更改,因为它们来自各种库(请注意,属性仅被简化)。 因此,当我收到这些实例时,我想以通用方式对待它们,这就是我创建G模型类的原因。有没有办法将G实例的属性分配给GAB,而不使用反射?它不是一个选项,因为它真的很慢。 Java 8解决方案没问题。

2 个答案:

答案 0 :(得分:3)

单一责任原则:G是消息,而不是消息工厂:

class G {
    private Class messageType;
    private Header header;
    private Data data;

    public G(Class<?> klass, Header header, Data data) {
        this.messageType = klass;
        this.header = header;
        this.data = data;
    }
}

class GFactory {
    private Map<Class<?>, Function<Object, G>> mappings;

    public <T> void register(
             Class<T> klass,
             Function<T, Header> headerExtractor,
             Function<T, Data> dataExtractor) {
        Function<Object, T> cast = klass::cast;
        mappings.put(klass, cast.andThen(t ->
             new G(klass, headerExtractor.apply(t), dataExtractor.apply(t)))); 
    }

    public G createG(Object message) {
        return mappings.get(message.getClass()).apply(message);
    }

    private GFactory() {
        register(A.class, A::getHeader, A::getData);
    }
}

我也会说不要从内部初始化GFactory,而是在外部进行。

答案 1 :(得分:1)

不是。

您唯一能做的就是:在这里解除两个职责。含义:

而不是让一个类负责检索属性执行此“instanceof”切换......您可以将其推送到两个不同班级。

含义:首先定义一些“数据传输类”,它给出G需要的东西,比如

class Foo {
  Foo(String header, ...) { ...
  String getHeader() { ...
  ...

然后你将“instanceof”切换到某种类型的工厂:

class FooFactory {
  Foo makeFooFrom(Object message) { ...

然后G使用FooFactory为任何传入消息获取Foo对象。

但问题是:不使用反射,独立类中具有不同字段的“隐含”复杂性碰巧具有相同的含义你无法解决。

我的解决方案唯一的“优势”:G不需要知道关于A,B,C的任何信息......它只知道Foo类。

但当然,FooFactory需要知道所有这些事情。大多数情况下,复杂性就像水一样 - 你可以用不同的方式,但你不能压缩它或使它“消失”。