从客户端选择创建实例 -java

create instance from client selection -java

我在网上浏览了一段时间。 我正在尝试动态创建 subclass 的实例,让我解释一下:

我有以下 class:

Public abstract  class Property

还有很多子 class 从这个 class 创建的,例如以下两个:

public   class PropertyDns extends Property

Public class PropretyNetBios extends Property

我想让客户端选择其中一个子class名称,然后我需要创建那个class的实例。

我将有很多扩展 属性 的子class,所以 switch-case 语句会很累: 所以:

switch (user_input){
case "PropertyDns ": return new PropertyDns();
case "PropretyNetBios": return new PropretyNetBios();
.
.
.
}

会很糟糕... 有什么想法吗?

您需要工厂和适合您的命名系统类(例如枚举),阅读工厂模式。这应该适合你。

public class PropertyFactory {
  public enum PropertyName {
    DNS,
    NET_BIOS
  }

  public Property createProperty(PropertyName name) {
    switch (name) {
        case DNS:
          return new PropertyDns();
        case NET_BIOS:
          return new PropretyNetBios(); 
    }
    return null; //Or throw an exception
  }
}

您可以使用以下两种方式之一来实现结果:

  1. 创建一个带有 String 参数的工厂方法,并根据该参数编写一个开关来为所需的对象提供服务。
  2. 第二个选项(此处推荐的方法)是使用 Class.newInstance[=22= 从 class 名称动态创建实例]

使用第二种方法将使您的解决方案易于扩展,添加新的 classes 不需要任何结构更改。

第二种方法的示例实现如下:

public Property getProperty(String name) {
    //Make sure the name contains full cannonical name of the class
    return (Property) Class.forName(name).newInstance();
}

正如我之前评论的那样,这个问题可以通过工厂模式来解决,如果 classes 的数量太多,你可以将工厂模式与注解处理器混合来生成工厂。您需要创建一个注解和相应的注解处理器。

这是您应该创建的注释示例:

@Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS)    
public @interface Property {
    String name();
    Class type();
}

您的 属性 classes 将如下所示:

@Property(name="DnsProperty", class=Property.class)
public class DnsProperty extends Property{
    ...
}

您需要实现自己的处理器来扩展 class

javax.annotation.processing.AbstractProcessor

并在

注册
/META-INF/services/javax.annotation.processing.Processor

想法是注释每个 class 以提供它的名称,并使用注释处理器生成工厂语句,从而使您免于编写令人筋疲力尽的 switch-case 语句。解释注释处理器,因为 switch-case 语句可能很累,所以,你可以在 Java 文档中阅读它,here is a blog post explaining annotation processors and here 是源代码。