Reputation: 3164
This is more of a style question, where I'm unsure what solution to my problem would be the "cleanest".
The implementation details are not important, what I want to do is the following:
I've got an abstract class that is extended by several subclasses which are all very similar in nature. I want to hide these classes from the client by making them instantiable only through a static method in the superclass which returns a superclass reference to a subclass instance (the concrete class is determined by the method parameters). So far so good, I believe that's a very common thing to do.
Now, these subclasses I'm talking about can be divided into two groups, one group, whose members require two parameters in order to be constructed and another group, whose members need an additional parameter.
So now my question is this: How can I let the client obtain both of these types via a static method like the one mentioned above. Do I provide two static methods with different paramter lists? Do I force the client to pass a zero on the third optional parameter that the first group doesnt need? Is there a design pattern for this? (I have considered the Builder pattern from Effective Java, but as far as I understnad it that ones usually used in a different context). Or do I modify my inheritance hierarchy?
Any answers would be appreciated!
EDIT:
I believe my question is a little bit convoluted at the moment, all add a little bit of code to make it clearer:
abstract class SuperClass{
public static SuperClass getSuperClass(String type, int i1, int i2, int optional) {
/*
*'type' alone determines which concrete subclass is instanciated
*'optional' is only needed for the construction for some of those 'types'
*so the implementation of this method might look like this:
*/
switch(type) {
case "1":
return new Subclass1(i1, i2);
break;
case "2":
return new Subclass2(i1, i2, optional);
break;
/*
*So the problem is this: always passing 'optional' is weird if it
*is then simply discarded in some cases.
*Overloading is weird as well because I don't want to split up
*the switch statement or check for exceptions in every case
*(when optional is/is not declared for types where it
*shouldn't/should be)
*/
}
}
Upvotes: 3
Views: 1627
Reputation: 15212
You have two options :
Option 1
Your static factory method
in the super class can be implemented using var-args :
public static SuperClass newInstace(int...parameters) {
SuperClass superClass = null;
if(parameters.length == 2) {
if(parameters[1]>=5) {//instantiate a subclass based on a value
super = new SubClass1(parameters[0],parameters[1]);
} else {
super = new SubClass2(parameters[0],parameters[1]);
}
} else if(parameters.length == 3) {
if(parameters[2]>=5) {
super = new SubClass3(parameters[0],parameters[1],parameters[2]);
} else {
super = new SubClass4(parameters[0],parameters[1],parameters[2]);
}
} else {
throw new IllegalArgumentException("Invalid number of parameters passed to newInstance. Expected number of parameters [min = 2, max = 3]")
}
return superClass;
}
Option 2
Alternately, you could overload the newInstance
method and have one that takes 2 parameters and the other that takes 3 parameters.
There are pros and cons of both approaches as described below :
Upvotes: 1
Reputation: 466
It depends. It sounds like that your superclass static method returns a SuperClass
instance. If so, you can return different subclass instances according to the additional parameter.
Consider an abstract class Vehicle
. Now two abstract classes SingleDeckVehicle
and MultiDeckVehicle
extend Vehicle
and let the first two parameters be the number of wheels and the number of seats, and the additional parameter be the number of decks of the vehicle. Then, the number of deck will be important and indeed your client will pass a 1
as the third argument if he/she wants a SingleDeckVehicle
instance.
However, you can also create another static method. Suppose you have defined a static method Vehicle.getVehicle(int wheelNo, int seatNo, int deckNo)
. You may also define another: Vehicle.getSingleDeckVehicle(int wheelNo, int seatNo)
which returns Vehicle.getVehicle(wheelNo, seatNo, 1);
.
A similar example is BorderFactory: http://docs.oracle.com/javase/7/docs/api/javax/swing/BorderFactory.html. I hope I understood your question correctly...
Upvotes: 0
Reputation: 533710
You could pass a configuration strings, or configuration object (e.g. Properties) which has as much detail as the implementation needs. It could be 1 or 100 arguments. However, for the caller there is one and only wrapping argument passed.
Upvotes: 0