简体   繁体   中英

Refactoring code with too many switch cases

I have inherited an application which needs some refactoring. The following is giving me some headaches. The original source code has too many switch cases like the following:

class Girl {
    //...
    void traditionalMakeUp() {
        switch (type) {
            case FRENCH:
                frenchMakeUp();
                break;
            case AFRICAN:
                africanMakeUp;
                break;
            case NORWEGIAN:
                norwegianMakeUp();
                .....

            case KOREAN:
                koreanMakeUp();
                .....
        }
    }
}

I am trying to refactor it like this:

abstract class Girl {
    //...
    abstract void makeUp();
}

class French extends Girl {
    void makeUp() {
        // makeUP
    }
}
class African extends Girl {
    void makeUp() {
        // makeUP
    }
}
class Norwegian extends Girl {
    void makeUp() {
        // makeUP
    }
}

// Somewhere in client code
girl.makeUp();

Is it the correct way to do it? If I didn't have 20+ cases in my switch, the strategy pattern would be fine.

Furthermore, I am reluctant to add 20+ classes just to fit the strategy design pattern. Is there another good way to refactor it?

It does look that inheritance is called for here depending on what other operations/switches exist in your application for Girl based on property type .

If that is the only switch, you can do like below,

Define an enum Girl with one abstract method - makeUp() and then implement that method right there for that enum type.

public enum Girl {

    FRENCH {
        public void makeUp() {
            Utility.frenchMakeUP();
        }
    },

    AFRICAN {
        public void makeUp() {
            Utility.africanMakeUP();
        }
    },

    NORWEGIAN {
        public void makeUp() {
            Utility.norwegianMakeUP();
        }
    },

    KOREAN {
        public void makeUp() {
            Utility.koreanMakeUP();
        }
    };

    public abstract void makeUp();

}

Your Utility class looks like this.

public class Utility {

    public static void frenchMakeUP() {

    }

    public static void africanMakeUP() {

    }

    public static void norwegianMakeUP() {

    }

    public static void koreanMakeUP() {

    }

}

Client code

Girl girl = Girl.FRENCH;
girl.makeUp();

You can organize multiple utility classes depending on how many functionalities exist and how to combine common functionality ie call , Utility.koreanMakeUP() from with in makeUp() can further be organized.

There are multiple ways to refactor such a scenario.

Inheritance is certainly one alternative to consider here. But depending on how deep the hierarchy might go and whether you find yourself needing to create helper classes or intermediate classes in the hierarchy to share common code, I would consider composition.

While what #makeUp does differs depending on the type of girl, perhaps there are semantically similarities where you can build small units of code (components) that you can then piece together in a component-like fashion.

I would rather do composition for Girl here and inheritance for the makeup. Depending on your domain it might be okay for a French Girl to wear African Makeup. Have a girl contain an object of type MakeUp.

Then I would do something like:

public class FrenchMakeUp extends MakeUp
{
    @Override
    public void apply(){...}
}

public class Girl
{
    public void makeUp(MakeUp makeUp)
    {
        makeUp.apply();
    }
}

In the client code:

girl.makeUp(new FrenchMakeUp());

This is to be closer to your attempted refactor but it doesn't solve the decision making. Perhaps you could have a Map to help you choose the correct makeup type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM