我是否可以构建一个Subclass实例,知道该子类的某些属性值

时间:2011-09-30 03:17:47

标签: java reflection

我有一个如此命名的属性类的层次结构,它表示我的域模型的单个属性。每个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?

提前谢谢你 丹尼尔

2 个答案:

答案 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;
  }
}