0

I have a universal mapper class with a method that determines which transformer implementation should be used. The indicator for this is an enum. The method looks like the following:

private void test() throws Exception {
    MyEnum nameEnum = ...
    ITransformer myTransformer;
    switch (nameEnum) {
    case ENUM1:
        mytransformer= new TransformerImpl1(this);
        mytransformer.doUnmarshal();
        break;
    case ENUM2:
        mytransformer= new TransformerImpl2(this);
        mytransformer.doUnmarshal();
        break;
    case ENUM3:
        mytransformer= new TransformerImpl3(this);
        mytransformer.doUnmarshal();
        break;
    ...// 40 x
    }
}

I know about filling a static map to avoid such switch/case statements, but here I have to return an instance of a class, so I think that won't work.

I think I also can't give the information which transformer to choose to the enum itself as I have to give the MapperClass as parameter to the transformer implementation.

But I think there must be a solution to avoid such long switch/case statements, even if in my case the classes have a "not so good" coupling.

soilworker
  • 1,317
  • 1
  • 15
  • 32
  • 2
    you can have a map for enum and transformerimpl. So get appropriate transformerimpl from map according to enum and then do unmarshal. No case, if else required at all – Sikorski Jan 02 '15 at 10:15
  • You failed to make clear what the problem is with this code. Your example code is a little weird, being a void method with no parameters. What's your use case? – wvdz Jan 02 '15 at 10:17
  • @Sikorski: Yes, I know the thing with the map, but how can I fill the map with the key/value pair when the value should be an instance of a class? – soilworker Jan 02 '15 at 10:21
  • @popovitsj: The problem is that I have 40 such case statements only for determining which transformer to use, I don't want to have it that way. There is nothing wrong with this code, but I want to have a better solution. – soilworker Jan 02 '15 at 10:36
  • 2
    Add an abstract method to the enum to do the transformation and implement it for each enum value. This has the advantage that you can't forget to implement it if you as a new value. – Alan Stokes Jan 02 '15 at 10:49
  • @Alan Stokes: That's the solution I was looking for, thx! How can I convert this comment to an answer? – soilworker Jan 02 '15 at 11:33
  • 1
    @Arbi's answer pretty much covers it. – Alan Stokes Jan 02 '15 at 13:16

2 Answers2

4

You can have something like:

public enum MyEnum {

 ENUM1(new TransformerImpl1()),
 ENUM2(new TransformerImpl2()),
 ENUM3(new TransformerImpl3()),
 ENUM4(new TransformerImpl4());

 ITransformer myTransformer;
 MyEnum(ITransformer myTransformer){
      this.myTransformer=myTransformer;
 }
 public ITransformer getTransformer() {
       return this.myTransformer;
 }
}

Then get the transformer of the enum instance and do the unmarchalling

bachr
  • 5,780
  • 12
  • 57
  • 92
  • This is a clean approach to have the behavior in the enums itself. But the TransformerImpl takes an argument of the class which uses it. The OP may have to give more context. Other than that, this is the correct solution. This approach is mentioned in Effective Java book. – Amudhan Jan 02 '15 at 10:36
  • 1
    @Amudhan you can pass instead a transformer builder to the enum constructor, then we you get it, you put the context you want and build the transformer. – bachr Jan 02 '15 at 10:43
1

If your transformers have the same contract (the same method), you can implement factory method pattern Check this link. This pattern provide more flexibility to add more functionnalities

Guillaume S
  • 1,462
  • 2
  • 19
  • 31
  • Then I have the same switch/case or if/else constellation when I have to determine which transformer I need. See the getShape() method of your link. – soilworker Jan 02 '15 at 10:33
  • Factory would also need to decide which TransformerImp instance should be returned based on passed enum argument, so you are just moving OP problem to different class. – Pshemo Jan 02 '15 at 10:33
  • Sorry bad link. So you can use Arbi's method.But if you want to have separate transformer instances you can use a map with your Enum as key and the transformer class as value like this.`Map> strategy; strategy.get(enum).newInstance();` – Guillaume S Jan 02 '15 at 10:37