Peter
Peter

Reputation: 3164

Static factory method for sub-classes with variable number of constructor arguments

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

Answers (3)

Chetan Kinger
Chetan Kinger

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 :

  1. When the frequency at which you expect new fields to be introduced in existing subclasses or the frequency at which you expect new subclasses to be introduced with more fields than the existing ones is extremely low, approach 1 is a better option.
  2. When the frequency at which you expect new fields to be introduced in existing subclasses or the frequency at which you expect new subclasses to be introduced with more fields than the existing ones is relatively higher, approach 2 is a better option since approach 1 will result in a very large method body.

Upvotes: 1

tonychow0929
tonychow0929

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

Peter Lawrey
Peter Lawrey

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

Related Questions