2

我有一个第三方 RPC-API,它提供了一个类似于java.sql.ResultSet(用于读取值)和java.sql.PreparedStatement(用于写入值)的接口。假设它看起来像这样:

public interface RemoteDeviceProxy {
    public void setBoolean(Boolean value);
    public void setInteger(Integer value);
    // ...

    public Boolean getBoolean();
    public Integer getInteger();
    // ...
}

我想为此 API 编写一个包装器,它使用泛型来创建特定类型的实例:

public class <T> RemoteVariable {
    private final RemoteDeviceProxy wrappedDevice;

    public RemoteVariable(RemoteDeviceProxy wrappedDevice) {
        this.wrappedDevice = wrappedDevice;
    }

    public T get() {
        // should call wrappedDevice.getBoolean() if T is Boolean, etc.
        // how to implement?
    }

    public void set(T newValue) {
        // should call wrappedDevice.setBoolean(newValue) if T is Boolean, etc.
        // implement using instanceof
    }
}

如何在我的通用包装器中实现 getter?我找到了这个答案,它深入解释了类似的场景,但我无法将其转移到我的问题上。具体来说,当我写这个时:

public T get() {
        Type[] actualTypeArguments = ((ParameterizedType) getClass())
                                         .getActualTypeArguments();
    }

我收到一个编译器错误,说我无法转换为ParameterizedType,我不明白为什么。谁能解释如何实现这一目标?

4

2 回答 2

2

这是一种方法:

public class <T> RemoteVariable {
    private final RemoteDeviceProxy wrappedDevice;
    private final Class<T> clazz;

    public RemoteVariable(RemoteDeviceProxy wrappedDevice, Class<T> clazz) {
        this.wrappedDevice = wrappedDevice;
        this.clazz = clazz;
    }

    public T get() {
        if(clazz == Boolean.class){return clazz.cast(wrappedDevice.getBoolean());}
        else if(clazz == Integer.class){return clazz.cast(wrappedDevice.getInteger());}
        // ...
    }

    // ...
}
于 2013-06-26T10:43:03.467 回答
2

我想了很久,最后想出了一个不同的方法:

首先,我为您的RemoteVariable课程添加了一个吸气剂:

protected RemoteDeviceProxy getWrappedProxy() {
    return wrappedProxy;
}

其次,我创建了一个稍后将由工厂使用的构建器接口:

public interface RemoteVariableBuilder {
    public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy);
}

Boolean然后我为...创建了非通用子类

public class RemoteBooleanVariable extends RemoteVariable<Boolean> implements RemoteVariableBuilder {

    public RemoteBooleanVariable(RemoteDeviceProxy wrappedProxy) {
        super(wrappedProxy);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) {
        return (RemoteVariable<T>) new RemoteBooleanVariable(wrappedProxy);
    }

    @Override
    public Boolean get() {
        return getWrappedProxy().getBoolean();
    }

    @Override
    public void set(Boolean value) {
        getWrappedProxy().setBoolean(value);
    }

}

...和整数...

public class RemoteIntegerBuilder extends RemoteVariable<Integer> implements RemoteVariableBuilder {

    public RemoteIntegerBuilder(RemoteDeviceProxy wrappedProxy) {
        super(wrappedProxy);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) {
        return (RemoteVariable<T>) new RemoteIntegerBuilder(wrappedProxy);
    }

    @Override
    public Integer get() {
        return getWrappedProxy().getInteger();
    }

    @Override
    public void set(Integer value) {
        getWrappedProxy().setInteger(value);
    }

}

实际上,一旦知道基类和接口,eclipse就创建了大部分代码。

最后一步是创建工厂

public class RemoteVariableFactory {
    private static final Map<String, RemoteVariableBuilder> BUILDERS = new HashMap<>();

    static {
        BUILDERS.put(Boolean.class.getName(), new RemoteBooleanVariable(null));
        BUILDERS.put(Integer.class.getName(), new RemoteIntegerBuilder(null));
        // add more builders here
    }

    public static <T> RemoteVariable<T> getRemoteVariable(RemoteDeviceProxy wrappedProxy, Class<T> typeClass) {
        RemoteVariableBuilder remoteVariableBuilder = BUILDERS.get(typeClass.getName());

        if (remoteVariableBuilder == null) {
            return null; // or throw an exception whichever is better in your case 
        }
        return remoteVariableBuilder.buildNewVariable(wrappedProxy);
    }
}

现在我们准备好创建新的 RemoteVariables...

RemoteVariable<Boolean> var1 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Boolean.class);
RemoteVariable<Integer> var2 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Integer.class);

总结一下,让我们快速比较一下 Eng.Fouad 的答案:

坏处:

  • 您需要为您提供的每种数据类型创建一个新类

优势:

  • 您只需在工厂的静态块中添加一行,而不是在 RemoteVariable 中的 getter 和 setter 中添加两个新 if 块
  • get 和 set 不必每次都通过 if-else-blocks
于 2013-06-27T07:55:33.987 回答