I have a Base interface that defines some common functionality. Now this base interface can be implemented by more than 50 classes each having some different additional methods. I want to have a static factory that will return an instance of any one of 50 classes depending on a parameter pass to that static factory method.
public interface Base {
public void a();
public void b();
}
public class myclass implements Base {
// a and b implementation
public String c() {
}
public String d() {
}
}
public class secondclass implements Base {
// a and b implementation
public String e() {
}
public String f() {
}
}
How can I implement a static factory method. I am unsure of return type
public synchronized static {return type} getInstance(String arg0) {
// do something and return any one class based on arg0
}
EDITS: A scenario
If the passed parameter is 300
I want to return object of class myclass
If parameter is 900
I want to return object of class secondclass
And so on. having so many conditions is not feasible.
NOT TO DO
public synchronized static {return type} getInstance(String arg0) {
// do something and return any one class based on arg0
if(arg0.equals("300")) {
return new myclass();
}
}
REASON: This will not be salable. I am developing a public API and class list may increase to 100 or may be 500. I hope my question is more clear now.
UPDATE: Very useful points highlighted here and this is what I thought of
public abstract class Base {
public abstract void a();
public abstract void b();
public synchronized staticabstract Base getInstance(String arg0);
}
public class myclass extends Base {
private myclass() {} // private constructor not publicly instantiate
// a and b implementation
public void c();
public void d();
@Override
public synchronized static abstract Base getInstance(String arg0) {
if(arg0.equalsIgnoreCase("300")) { // only 1 if condition
return new myclass();
}
}
}
public class secondclass extends Base {
private secondclass() {} // private constructor not publicly instantiate
// a and b implementation
public void e();
public void f();
@Override
public synchronized static abstract Base getInstance(String arg0) {
if(arg0.equalsIgnoreCase("900")) { // only 1 if condition
return new secondclass();
}
}
}
Client side:
one applicaiton
Base b=Base.getInstance(300);
if(b instanceof myclass) {
}
second application
Base b=Base.getInstance(900);
if(b instanceof secondclass) {
}
A better approach would be to generify the static method:
static <T extends Base> T create(Class<T> type){
// create concrete instance of type T and return it
}
so now the create
method is parameterized by the actual concrete type Class
object. You can use type
to create the appropriate sub-type, either via reflection or using nested if
statements.
Using generics has the advantage of giving you strong type safety for free, so you can avoid unchecked casts and go home after work with no worries.
EDIT: as an example if you had a no-arg constructor in each sub-class you could implement the above as:
return type.newInstance();
EDIT 2: To sum up the discussion, if the factory can't take the type or the logic to create the object depends in a non trivial way on the value of the argument, the only option is the following:
static Base create(String someParameter){
// create the concrete class and return it
}
And the client code will look like:
Base b = create("myArgument");
if(b instanceof SomeDerived){
SomeDerived d = (SomeDerived) b;
// use d
} else if(b instanceof OtherDerived){
// you get the idea
}
Not ideal but there's no way to generify the create
method without an instance of Class<? extends Base>
.