Java 使用相同的getter泛化第三方类,而不使用反射
下面是一个示例代码:Java 使用相同的getter泛化第三方类,而不使用反射,java,generics,java-8,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; priv
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();
}
}
}
模型类A
、B
和C
不能更改,因为它们来自不同的库(请注意,这些属性只是简化的)。
因此,当我收到这些实例时,我希望以一种通用的方式来处理它们,这就是为什么我创建了一个G
model类。有没有一种方法可以将属性分配给G
实例,而不必将G
与a
、B
和C
紧密地联系在一起,而不必使用反射?这不是一个选择,因为它真的很慢。Java 8解决方案还可以。不太好
你能做的唯一一件事是:将这两个职责分离开来。意思是:
而不是让一个类负责检索属性并执行此“instanceof”切换。。。你可以把它分为两类
意思:首先定义一些“数据传输类”,它为G提供了G需要的东西,比如
class Foo {
Foo(String header, ...) { ...
String getHeader() { ...
...
然后将“instanceof”切换移动到某种工厂中,其方法如下:
class FooFactory {
Foo makeFooFrom(Object message) { ...
然后G使用该FooFactory为任何传入消息获取一个Foo对象
但问题是:如果不使用反射,在独立的类中有不同的字段的“隐式”复杂性是无法解决的,这些字段恰好对您具有相同的含义
我的解决方案唯一的“优势”是:G不需要知道关于A、B、C的任何信息。。。它只知道Foo类
但当然,食品工厂需要知道所有这些事情。大多数情况下,复杂性就像水——你可以让它以不同的方式流动,但你不能压缩它或让它“消失”。不太可能
你能做的唯一一件事是:将这两个职责分离开来。意思是:
而不是让一个类负责检索属性并执行此“instanceof”切换。。。你可以把它分为两类
意思:首先定义一些“数据传输类”,它为G提供了G需要的东西,比如
class Foo {
Foo(String header, ...) { ...
String getHeader() { ...
...
然后将“instanceof”切换移动到某种工厂中,其方法如下:
class FooFactory {
Foo makeFooFrom(Object message) { ...
然后G使用该FooFactory为任何传入消息获取一个Foo对象
但问题是:如果不使用反射,在独立的类中有不同的字段的“隐式”复杂性是无法解决的,这些字段恰好对您具有相同的含义
我的解决方案唯一的“优势”是:G不需要知道关于A、B、C的任何信息。。。它只知道Foo类
但当然,食品工厂需要知道所有这些事情。大多数情况下,复杂性就像水——你可以让它以不同的方式运行,但你不能压缩它或让它“消失”。单一责任原则: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);
}
}
G类{
私有类消息类型;
私有报头;
私人数据;
公共G(类klass、标题、数据){
this.messageType=klass;
this.header=头;
这个数据=数据;
}
}
类工厂{
私有映射单一责任原则: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);
}
}
G类{
私有类消息类型;
私有报头;
私人数据;
公共G(类klass、标题、数据){
this.messageType=klass;
this.header=头;
这个数据=数据;
}
}
类工厂{
私有映射没有机会。因为它们没有公共的超类或实现相同的接口,所以您必须像您已经做的那样使用instanceof
列出它们,或者使用反射。我只能为您提供一个覆盖get方法的类:类G{Data get(a a){return a.getData();}Data get(B){return B.getData();Data get(cc){return C.getData();}}反射“真慢”吗?有些库一直在使用它,没有任何问题。@eis我们在一秒钟内处理1000条消息。反射方法不需要基准测试。是的,我同意你会注意到这种情况。不可能。因为它们没有公共超类或实现相同的接口,你必须用instanceof
我只能给你提供一个覆盖get方法的类:类G{Data get(a){return a.getData();}Data get(B){return B.getData();Data get(C){return C.getData();}}反射“真的很慢”吗?有些库一直在使用它,没有任何问题。@eis我们在一秒钟内处理1000条消息。反射方法不需要基准测试。是的,我同意你会注意到这种情况。很好!我终于可以摆脱if-else条件了。让我看看是否可以将GFactory的初始化放在spring上下文文件上。看起来像nice解决方案。虽然我不完全理解它在做什么;-)@GhostCat:一个解决方案,你不理解,就不会是一个好的解决方案。但是如果你专注于寄存器(a.class,a::getHeader,a::getData),它就不难理解了
line作为解决方案的关键。当然,您必须为B
和C
添加行。请注意,如果A
、B
或C
可能有子类,而这些子类不在OP的控制范围内,则此解决方案需要额外的工作。@JulioD-很抱歉,您一方面使用了Spring,但您担心r另一方面是反射速度?这没有意义(除非你真的对每条消息从头开始反射)很好!我终于可以摆脱if-else条件。让我看看是否可以将GFactory的初始化放在spring上下文文件上。看起来像一个ni