从客户端选择创建实例 -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
}
}
您可以使用以下两种方式之一来实现结果:
- 创建一个带有
String
参数的工厂方法,并根据该参数编写一个开关来为所需的对象提供服务。
- 第二个选项(此处推荐的方法)是使用 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 是源代码。
我在网上浏览了一段时间。 我正在尝试动态创建 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
}
}
您可以使用以下两种方式之一来实现结果:
- 创建一个带有
String
参数的工厂方法,并根据该参数编写一个开关来为所需的对象提供服务。 - 第二个选项(此处推荐的方法)是使用 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 是源代码。