Reputation: 161
I've been looking around the web for a while. I'm trying to create an instance of a subclass dynamically, let me explain:
I have the following class:
Public abstract class Property
And a lot of sub class created from this class, for example the following two:
public class PropertyDns extends Property
Public class PropretyNetBios extends Property
I want the client to choose one of the subclass name, and then I need to create an instance of that class.
I'm going to have a lot of subclass that extends Property so switch-case statements will be exhausting: So:
switch (user_input){
case "PropertyDns ": return new PropertyDns();
case "PropretyNetBios": return new PropretyNetBios();
.
.
.
}
will be terrible... any ideas?
Upvotes: 0
Views: 172
Reputation: 1673
As I commented before, this problem can be solved with the Factory Pattern, if the number of classes is too large you can mix the Factory Pattern with an Annotation Processor to generate the factory. You need to create an annotation and a corresponding annotation processor.
Here is an example of the annotation you should create:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS)
public @interface Property {
String name();
Class type();
}
Your property classes will look like this:
@Property(name="DnsProperty", class=Property.class)
public class DnsProperty extends Property{
...
}
You need to implement your own processor extending the class
javax.annotation.processing.AbstractProcessor
and register it at
/META-INF/services/javax.annotation.processing.Processor
The idea is to annotate each class to provide it's name, and generate the factory statements with the annotation processor, saving you from writing the exhausting switch-case statements. Explaining the annotation processors, as switch-case statements can be exhausting, so, you can read about it in the Java documentation, here is a blog post explaining annotation processors and here is the source code.
Upvotes: 1
Reputation: 2421
You can use one of the following two ways to achieve the result:
String
parameter, and based on the parameter, write up a switch to serve the required object.Using the second approach would make your solution easily extendable, and the addition of new classes won't need any structural changes.
A sample implementation of the second approach would be like:
public Property getProperty(String name) {
//Make sure the name contains full cannonical name of the class
return (Property) Class.forName(name).newInstance();
}
Upvotes: 3
Reputation: 1673
You need a Factory and a proper naming system for you classes(for example an enumeration), read about Factory pattern. This should work for you.
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
}
}
Upvotes: 0