2

I have the following piece of code. It's kind of a factory function that retrieves an instance of a writer base on it's type. Notice that the type is an enum.

public Writer getWriter(WriterTypeEnum type){
  switch(type){
    case A: new AWriter() break;
    case B: ... break;
    case C: ... break;
    ...
  }
}

The problem is I have about 30 cases. What can I do to reduce them or to not implement them at all?

I solved cases like this in the past using strategy pattern but here I am facing an old enum used in the entire app. The other problem is that I cannot inject spring beans into this enum. Some of the instances from switch cases are beans.

The WriterTypeEnum has an ID that is coming from UI and based on that ID I have to determine the right instance.

tzortzik
  • 4,993
  • 9
  • 57
  • 88
  • 2
    It's unclear what you're asking for here. You don't have to implement all possible cases in a switch statement... just use `default` for anything you don't want to handle explicitly. Another option would be to make the enum itself capable of creating a writer - but without knowing more about it, we can't really tell. – Jon Skeet Jul 28 '16 at 10:48
  • 1
    You could use Map and get the Object by passing type. Check this it may help you :-- http://stackoverflow.com/questions/27993819/hashmap-vs-switch-statement-performance – Shekhar Khairnar Jul 28 '16 at 10:53

4 Answers4

4

You can setup your enum to have an abstract method

public abstract Writer getWriter();

and after that, all your instances would have to implement that method, for example

public enum YourEnum{
    FIRST(){
        public Writer getWriter(){
            return null;
        }
    }, ... // other enums

    public abstract Writer getWriter();

}

or you could omit the break in your switch, if there are repeating statements

Draken
  • 3,134
  • 13
  • 34
  • 54
Andrii Plotnikov
  • 3,022
  • 4
  • 17
  • 37
  • I already have the methods implemented inside some spring services. For those who are not instantiated by spring, your method will work. In my case I have both types of implementation and you cannot inject a spring bean into an enum. – tzortzik Jul 29 '16 at 08:01
  • 1
    @tzortzik um, you cannot autowire, but I think you can grab aplication context and find bean by type? or you could follow their advice: stackoverflow.com/a/21119815/5070158 ; and inject into inner class. – Andrii Plotnikov Jul 29 '16 at 08:05
2

How about having a look up map of writer names, then creating an instance using reflection?

String writerNameJustFound = mapOfWriters.get(type);

Object instance = Class.forName(writerNameJustFound).newInstance();

jdlacy
  • 96
  • 3
1

Another type of answer I come across is to use inheritance, i.e. make WriterTypeEnum into WriterType.

public Writer getWriter(WriterType type){
    return type.getWriter();
}

that way, all you have to do is pass correct child of WriterType, and you will never touch code inside getWriter. The problem lies in context, whether such solution is possible to implement.

Andrii Plotnikov
  • 3,022
  • 4
  • 17
  • 37
0

All of the previous solution are welcome and most probably some will work in my case.

My solution was to create another object that has a Set<WriterMapping>. In this object I store the value of WriterEnumType and its correspondent Writer.

tzortzik
  • 4,993
  • 9
  • 57
  • 88