这只是一个半严肃的建议,但我们可以将mikera 的答案修改为类型安全。
假设我们有:
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 行中工作的通用构建器,每个实体都有一个包含单个单行方法的子类。