这只是一个半严肃的建议,但我们可以将mikera's answer 修改为类型安全。
假设我们有:
public class A {
private final String foo;
private final int bar;
private final Date baz;
}
然后我们写:
public abstract class AProperty<T> {
public static final AProperty<String> FOO = new AProperty<String>(String.class) {};
public static final AProperty<Integer> BAR = new AProperty<Integer>(Integer.class) {};
public static final AProperty<Date> BAZ = new AProperty<Date>(Date.class) {};
public final Class<T> propertyClass;
private AProperty(Class<T> propertyClass) {
this.propertyClass = propertyClass;
}
}
还有:
public class APropertyMap {
private final Map<AProperty<?>, Object> properties = new HashMap<AProperty<?>, Object>();
public <T> void put(AProperty<T> property, T value) {
properties.put(property, value);
}
public <T> T get(AProperty<T> property) {
return property.propertyClass.cast(properties.get(property));
}
}
高级设计模式和/或晦涩的 Java 技巧的爱好者会认为这是一个类型安全的异构容器。感谢我也没有使用getGenericSuperclass()。
然后,回到目标类:
public A(APropertyMap properties) {
foo = properties.get(AProperty.FOO);
bar = properties.get(AProperty.BAR);
baz = properties.get(AProperty.BAZ);
}
这都是这样使用的:
APropertyMap properties = new APropertyMap();
properties.put(AProperty.FOO, "skidoo");
properties.put(AProperty.BAR, 23);
A a = new A(properties);
仅仅为了lulz,我们甚至可以给地图一个流畅的界面:
public <T> APropertyMap with(AProperty<T> property, T value) {
put(property, value);
return this;
}
这让调用者可以写:
A a = new A(new APropertyMap()
.with(AProperty.FOO, "skidoo")
.with(AProperty.BAR, 23));
您可以对此进行许多小改进。 AProperty 中的类型可以更优雅地处理。 APropertyMap 可以有一个静态工厂而不是构造函数,如果你喜欢这种东西,可以使用更流畅的代码风格。 APropertyMap 可以扩展一个 build 方法,该方法调用 A 的构造函数,本质上将它变成一个构建器。
您还可以使其中一些对象更通用。 AProperty 和 APropertyMap 可以有通用的基类来完成功能位,以及非常简单的A 特定的子类。
如果您感觉特别企业,并且您的域对象是 JPA2 实体,那么您可以使用元模型属性作为属性对象。这让地图/构建器做更多的工作,但它仍然很简单;我有一个 45 行的通用构建器,每个实体都有一个子类,包含一个单行方法。