Converting many 'if else' statements to a cleaner approach

JavaDesign Patterns

Java Problem Overview


My code here detects if the mimeType is equals to some MIME type, if it is, it will do a certain conversion

public void convertToMp3(File src, File target,String mimeType){
    if(mimeType.equals("audio/mpeg")){
        ...
    }else if(mimeType.equals("audio/wav")){
        mp3ToWav();
    }else if(mimeType.equals("audio/ogg")){
        ...
    }else if(...){
    ... //More if and else here
}

I have shortened my code, because it has a lot of else if statements, What design pattern is suitable for removing many if and else or else if statements?

Java Solutions


Solution 1 - Java

You could have a Converter interface. Then you could create a class for each Mimetype like:

public interface Converter {
    
    public void convertToMp3();
    public void convertToOgg();

}

public class MpegConverter implements Converter {

    public void convertToMp3() {
        //Code here
    }

    public void convertToOgg() {
        //Code here
    }

}

You would need a class like this for each converter. Then you could set up a map like this:

Map<String, Converter> mimeTypeMap = new HashMap<String, Converter>();

mimeTypeMap.put("audio/mpeg", new MpegConverter());

Then your convertToMp3 method becomes like this:

Converter converter = mimeTypeMap.get(mimeType);
converter.convertToMp3();

Using this approach you could easily add different converters in the future.

All untested, probably doesn't compile, but you get the idea

Solution 2 - Java

If you use pre-JDK7, you may add an enum for all MIME types:

  public static enum MimeTypes {
      MP3, WAV, OGG
  }

  public class Stuff {
      ...
      switch (MimeTypes.valueOf(mimeType)) {
          case MP3: handleMP3(); break;
          case WAV: handleWAV(); break;
          case OGG: handleOGG(); break;
      }
  }

And have a look at the Stack Overflow question Java - Convert String to enum on how to convert Strings to enums.

Solution 3 - Java

Consider using the Strategy design pattern and a Map to dispatch to the appropriate strategy. Particularly useful if you you will need additional functionality, in addition to a conversion for a particular mimeType, or the convertors are large and complicated code and you would want to place each convertor in its own .java file.

 interface Convertor {
    void convert(File src, File target);
 }

 private static void convertWav(File src, File target) {
    ...
 }

 ...

 private static final Map< String, Convertor > convertors = new ...;
 static {
    convertors.put("audio/wav", new Convertor {
       void convert(File src, File target) {
          convertWav(src, target);
       }
    });
    convertors.put("audio/ogg", new Convertor {
       void convert(File src, File target) {
          convertOgg(src, target);
       }
    });
    ...
 }

 public void convertToMp3(File src, File target, String mimeType){
     final Convertor convertor = convertors.get(mimeType);
     if (convertor == null ) {
        ...
     } else {
        convertor.convert(src, target);
     }
 }

Solution 4 - Java

If you run the same methods for each case you should check State pattern

Solution 5 - Java

If you are using JDK 7, you can use switch-case construct:

See: https://stackoverflow.com/questions/338206/switch-statement-with-strings-in-java

For prior versions, if-else is the only choice.

Solution 6 - Java

It's definitely a Strategy design pattern. But you have a big problem in your general design. It's not a good programming habit to use String to identify a type. Simply because it's easily editable and you can make a grammar mistake and spend all the afternoon looking for a programming mistake. You can avoid using map<>.

I suggest the following:

  1. Extend class File. The new class adds a new attribute FileType and a new method convertTo(FileType) to class File. This attribute holds its type: “audio” , “wav”... and again don't use String, Use Enum. In this case I called it FileType. Extend File as much as you want: WavFile, AudioFile...
  2. Use a Strategy dp to create your converters.
  3. Use a Factory dp to initialize the converters.
  4. Since every File knows its own type and the target type (use convertTo() method to specify the target type) it will call the factory to get the correct Converter automatically!!!

This design is scalable and you can add as much as you need FileType and converters. The answer you vote for is misleading!!!! There is a big difference between coding and hacking.

Solution 7 - Java

If you are not using Java 7 you could create an enum and use that value with a switch case. You then only need to pass the enum value (rather than a file, I don't why you are doing that). It would look neater too.

These should help with what you want to do:

 [Java Enum Examples][1] - 
 [Java Switch Case examples][2]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser962206View Question on Stackoverflow
Solution 1 - JavacowlsView Answer on Stackoverflow
Solution 2 - JavapgrasView Answer on Stackoverflow
Solution 3 - JavaRaedwaldView Answer on Stackoverflow
Solution 4 - JavaMarcin SzymczakView Answer on Stackoverflow
Solution 5 - JavaAzodiousView Answer on Stackoverflow
Solution 6 - JavageorgeView Answer on Stackoverflow
Solution 7 - JavaSkepiView Answer on Stackoverflow