creating objects and polymorphism

design-patterns, java, polymorphism

Solution

Question is "if" you need a factory. The factory is meant to manage the creation of instances an not so much the behavior of related instances.

Otherwise, you're just looking at basic inheritance. Something like..

class Actor{
  public void act(){
    System.out.println("I act..");
  }
}

class StuntActor extends Actor {
  public void act(){
    System.out.println("I do fancy stunts..");
  }
}

class VoiceActor extends Actor {
  public void act(){
    System.out.println("I make funny noises..");
  }
}

To Use, you can just instantiate the type of actor you need directly.

Actor fred = new Actor();
Actor tom = new VoiceActor();
Actor sally = new StuntActor();

fred.act();
tom.act();
sally.act();

Output:

I act..
I make funny noises..
I do fancy stunts..

EDIT:

If you need to centralize the creation of the Actors..aka vis a Factory, you will not be able to get away from some kind of switching logic--in which case..i'll typically use an enumeration for readability:

public class Actor{
  public enum Type{ REGULAR, VOICE, STUNT }

  public static Actor Create(Actor.Type type){
    switch(type) {
      case VOICE:
        return new VoiceActor();
      case STUNT:
        return new StuntActor();
      case REGULAR:
      default:
        return new Actor();
    }
  }

  public void act(){
    System.out.println("I act..");
  }
}

Usage:

Actor some_actor = Actor.Create(Actor.Type.VOICE);
some_actor.act();

Output:

I make funny noises..

Problem

I want to avoid using tagged classes and big if-else blocks or switch statement and use polymorphism with a class hierarchy instead, which I believe is better practice. For example, something like the below, where the choice of executed method is dependent only one one field of an object of type Actor. ``` switch(actor.getTagField()) { case 1: actor.act1(); break; case 2: actor.act2(); break; [...] } ``` would become ``` actor.act(); ``` and the act method would be overridden in subclasses of Actor. However, the most obvious way to decide at runtime which subclass to instantiate looks awfully similar to the original: ``` Actor newActor(int type) { switch(type) { case 1: return new Actor1(); case 2: return new Actor2(); [...] } } ``` so it seems like nothing has really been gained; the logic has just been moved. What is a better way to do this? The only way I can come up with involved implementing a factory class for each subclass of Actor, but this seems rather cumbersome for such a simple problem. Am I overthinking this? It just seems like there's no point making the original change if I just do pretty much the same thing elsewhere.

Original source