Object Creation and Polymorphism

I want to avoid using tagged classes and large if or else blocks or the switch statement, and instead use polymorphism with a class hierarchy, which in my opinion is best practice.

For example, something like below, where the choice of the executed method depends on only one field of an object of type Actor.

switch(actor.getTagField()) { case 1: actor.act1(); break; case 2: actor.act2(); break; [...] } 

will become

 actor.act(); 

and the act method will be overridden in subclasses of Actor.

However, the most obvious way to decide at runtime which subclass to instantiate looks terribly similar to the original:

 Actor newActor(int type) { switch(type) { case 1: return new Actor1(); case 2: return new Actor2(); [...] } } 

therefore, it seems that nothing happened; the logic has just been moved.

Which is better for this? The only way I can come up with is to implement the factory class for each subclass of Actor, but for such a simple problem it looks rather cumbersome.

Can I say this? It seems like it makes no sense to make the initial change if I just do almost the same thing elsewhere.

+7
source share
3 answers

The question is if you need a factory. factory is designed to control instantiation not so much for the behavior of related instances.

Otherwise, you are 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 simply create an instance of the type that 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 Actors..aka in relation to Factory, you will not be able to get away from some kind of switching logic - in this case ... I usually 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.."); } } 

Using:

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

Output:

 I make funny noises.. 
+4
source

Switch statements are not pure evil. This is truly a duplication that you want to eliminate with a better design. Often you find that the same switch statement is displayed in different (remote) places in your code - you don’t have to do the same, but include the same data. Introducing polymorphism, you combine these switches as different methods of the same object.

This does two things: first, it reduces several switches to one switch inside the factory, and it combines the decomposed logic, which probably depends on similar data. This data will turn into member variables in your objects.

It is also worth noting that you do not always get the switch statement under the hood of your factory. Perhaps you could scan the class path at startup and build HashMap types that implement the interface. For example, consider an implementation of a socket protocol such as SMTP. You can have objects named HeloCommand , MailFromCommand , etc .... and find a suitable object to process the message by matching the socket command with the class name.

+2
source

I believe that you can do this with an abstract factory pattern ...

This is an example:

 abstract class Computer { public abstract Parts getRAM(); public abstract Parts getProcessor(); public abstract Parts getMonitor(); } class Parts { public String specification; public Parts(String specification) { this.specification = specification; } public String getSpecification() { return specification; } } 

We have two classes that extend Computer

 class PC extends Computer { public Parts getRAM() { return new Parts("512 MB"); } public Parts getProcessor() { return new Parts("Celeron"); } public Parts getMonitor() { return new Parts("15 inches"); } } class Workstation extends Computer { public Parts getRAM() { return new Parts("1 GB"); } public Parts getProcessor() { return new Parts("Intel P 3"); } public Parts getMonitor() { return new Parts("19 inches"); } } 

And finally, we have

 public class ComputerType { private Computer comp; public static void main(String[] args) { ComputerType type = new ComputerType(); Computer computer = type.getComputer("Workstation"); System.out.println("Monitor: "+computer.getMonitor().getSpecification()); System.out.println("RAM: "+computer.getRAM().getSpecification()); System.out.println("Processor: "+computer.getProcessor().getSpecification()); } public Computer getComputer(String computerType) { if (computerType.equals("PC")) comp = new PC(); else if(computerType.equals("Workstation")) comp = new Workstation(); return comp; } } 
+1
source

All Articles