我有一个如此命名的属性类的层次结构,它表示我的域模型的单个属性。每个Attribute类都有一个唯一的String id属性。 我还有一个AttributeFactory,它有一个基于id检索Attribute实例的方法。
public class Attribute {
private String id;
private AttributeType type;
.......
.......
public Attribute(String id){
this.id=id;
}
public void setID(String id){
this.id=id;
}
public String getID(){
return this.id;
}
.......
.......
}
Factory的界面看起来像
public interface IAttributeFactory {
Attribute getAttributeByID(String id);
}
此接口的一个实现可以将HashMap作为所有已定义属性的存储库。
属性子类的一个例子是:
public class ClientCode extends Attribute {
public ClientCode(){
super("clientCode");
this.setType(AttributeType.CHAR_TYPE);
}
........
........
}
问题是,我们可以使用反射或任何其他东西构建属性子类的新实例,只知道该子类的id,因此实现上面定义的接口,而无需定义HashMap并添加每个新定义的子类到HashMap?
提前谢谢你 丹尼尔
答案 0 :(得分:1)
如果客户端代码任意选择ID,则无法知道哪个ID属于哪个Attribute子类。但是,如果您可以以某种方式强制执行模式,那么可以通过仅知道ID来实例化子类。你可以通过反思来做到这一点。
以下示例代码如何通过反射创建新实例:
public void createInstanceOfSubclass(String id) {
try {
Class cls = Class.forName(convertIDToClassName(id));
Class parameterTypes[] = new Class[1];
parameterTypes[0] = String.TYPE;
Constructor ct = cls.getConstructor(parameterTypes);
Object arglist[] = new Object[1];
arglist[0] = id;
Object subclassInstance = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
[这只是示例代码;例如,可以在实际实现中改进错误处理。]
基本上,您必须编写convertIDToClassName(String)方法才能将ID转换为类名。没有这种关联,就不可能将这两者联系起来。
另一个想法是属性的ID由您计算;意味着Attribute类设置自己的ID字段。因此,您可以直接将子类名称和ID字段链接在一起。因此,可以通过ID实例化子类。
在任何情况下,个人评论都是避免反思并坚持在代码中创建类(可能会在工厂类中的某处取出实例化代码,以便主代码获得closed for modification)。
答案 1 :(得分:0)
你需要一个工厂来创建属性的特定子类的实例,对吧?让我们使用典型的工厂模式来做到这一点。
//TODO make this a singleton
public final class ClientFactory implements IAttributeFactory {
public static final String CLIENT_CODE = "clientCode"; //TODO use enum
/** This can return a null */
public final Attribute getAttributeByID(String id) { //TODO rename this getter to something like create
if (null == id) return null;
if(id == CLIENT+CODE)
return new ClientCode(CLIENT_CODE);
return null;
}
}