1

I am aware of how to replace a switch statement through polymorphism, like it is explained for instance here.

In my case however I have two Enum:

public enum EleType {
    INTEGER, 
    CHARACTER
}

and

public enum SorterType {
    BUBBLE,
    INSERTION
}

and the switch/if I would like to refactor has the structure:

if ( eleType == EleType.INTEGER ) {
    switch ( sorterType ) {
        case BUBBLE:
             composition = new SorterComposition<Integer>(new BubbleSort<Integer>(), randomList);
             break;
        case INSERTION:
             composition = new SorterComposition<Integer>(new InsertionSort<Integer>(), randomList);
             break;
    }
} else if ( eleType == EleType.CHARACTER ) {
    switch ( sorterType ) {
        case BUBBLE:
             composition = new SorterComposition<Character>(new BubbleSort<Character>(), randomList);
             break;
        case INSERTION:
             composition = new SorterComposition<Character>(new InsertionSort<Character>(), randomList);
             break;
    }
}

Because both enum appear together and both affect the SorterComposition part, I am unsure how to refactor this structure. Also I am unsure how to get the "Integer"/"Character" generic types from EleType.INTEGER or EleType.CHARACTER respectively without using conditional statements.

2 Answers 2

1

Do you mean that you implement the code like this?

public static <T> SorterComposition<T> createComposition(SorterType type, <Type of randomList>) {
    switch (type) {
        case BUBBLE:
            return new SorterComposition<T>(new BubbleSort<T>(), randomList);
        case INSERTION:
            return new SorterComposition<T>(new InsertionSort<T>(), randomList);
        default:
            throw <Exception>
    }
}

Or, you can change the EleType class a little bit.

public enum EleType {
    INTEGER(Integer.class), CHARACTER(Character.class);
    private EleType(Class cl) { this.classType = cl; }
    public Class getClassType() { return classType; }
    private final Class classType;
}

and use this code instead of the createComposition above.

public static <T> SorterComposition<T> createComposition(Class<T> eleType, SorterType type, <Type of randomList>) {
    switch (type) {
        case BUBBLE:
            return new SorterComposition<T>(new BubbleSort<T>(), randomList);
        case INSERTION:
            return new SorterComposition<T>(new InsertionSort<T>(), randomList);
        default:
            throw <Exception>
    }
}

and when you use it, use composition = createComposition(eleType.getClassType(), sorterType, randomList);


To avoid switch of SorterType in a gentle way, maybe you can use in add a Supplier field into SorterType.

public enum SorterType {
    BUBBLE(() -> new BubbleSort()),
    INSERTION(() -> new InsertionSort());

    private SorterType(Supplier<Sort> supplier) {
        this.supplier = supplier;
    }

    public Sort getSort() {
        return supplier.get();
    }

    private final Supplier<Sort> supplier;
}
Sign up to request clarification or add additional context in comments.

4 Comments

Changing the EleType seems to solve my second problem (mapping from EleType to Integer.class, etc). However I still want to get rid of the switch statement somehow.
How about the code in the update? Add a field to EleType, and when calling createComposition, pass in eleType.getClassType().
How does this get rid of the switch of SorterType ?
I would avoid the Supplier approach, as it creates raw types (meaning, new BubbleSort instead of new BubbleSort<Integer>).
0

You could use double dispatch. I have provided a skeleton implementation below. However some consider double dispatch a code smell. In this instance your EleType seems suspect to me. All you are doing with it in this example is use it for your generic type declaration.

    public enum EleType {
    INTEGER {
        SorterComposition getSorter(SorterType s) {
            return s.getIntegerSorter();
        }
    }, 
    CHARACTER{
        SorterComposition getSorter(SorterType s) {
            return s.getChracterSorter();
        }

    };

    abstract SorterComposition getSorter(SorterType s);
};

public enum SorterType {
    BUBBLE {
        SorterComposition getIntegerSorter() {return new BubbleSort<Integer>();}
        SorterComposition getChracterSorter() {return new BubbleSort<Character>();}
    },
    INSERTION{
        SorterComposition getIntegerSorter() {return new InsertionSort<Integer>();}
        SorterComposition getChracterSorter() {return new InsertionSort<Character>();}
    };

    abstract SorterComposition getIntegerSorter();
    abstract SorterComposition getChracterSorter();

};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.