I am writing a Factory class that depending on a given parameter would return various implementations of an interface:
class Factory {
public MyType getType(String param) {
if (param.equals("A")) {
return new MyTypeA();
} else if (param.equals("B")) {
return new MyTypeB();
}
}
Now instead of new
I want to leverage Spring's dependency injection capabilities. I want to use @Annotation based autowiring.
First thing coming to mind is to use @Autowire
on field like so:
class Factory {
@Autowired
private MyTypeA myTypeA;
@Autowired
private MyTypeB myTypeB;
public MyType getType(String param) {
if (param.equals("A")) {
return myTypeA;
} else if (param.equals("B")) {
return myTypeB;
}
}
But then I remember that field autowiring is not recommended because it is hard to unit test such classes.
Next thing I could try would be to use setter level autowiring to allow for testing:
class Factory {
private MyTypeA myTypeA;
private MyTypeB myTypeB;
public MyType getType(String param) {
if (param.equals("A")) {
return myTypeA;
} else if (param.equals("B")) {
return myTypeB;
}
@Autowired
public void setMyTypeA(MyTypeA a) {
this.myTypeA = a;
}
@Autowired
public void setMyTypeB(MyTypeB b) {
this.myTypeB = b;
}
}
OK this looks better, but wait, there is more - I want my class to be immutable so I want my private fields to be final and only get populated at constructor time. So next thing I could try would be constructor based injection:
class Factory {
private final MyTypeA myTypeA;
private final MyTypeB myTypeB;
public Factory(MyTypeA myTypeA, MyTypeB myTypeB) {
this.myTypeA = myTypeA;
this.myTypeB = myTypeB;
}
public MyType getType(String param) {
if (param.equals("A")) {
return myTypeA;
} else if (param.equals("B")) {
return myTypeB;
}
}
Looks good, but here comes the question - if I have 20 different types I can return from this factory depending on the param value, I can't create a 20 param constructor.
Please suggest, what would be the best approach in this case (trying to avoid xml based autowiring).
Thank you