Switch statements (or their equivalent, if…elseif…elseif… structures) aren't inherently bad. They become bad only when they make your design more complicated or rigid than it needs to be. In that case, it's best to refactor away from switch statements to a more object-based or polymorphic solution.
Replace Conditional Dispatcher with Command (191) describes how to break down a large switch statement into a collection of Command [DP] objects, each of which may be looked up and invoked without relying on conditional logic.
Move Accumulation to Visitor (320) describes an example where switch statements are used to obtain data from instances of classes that have different interfaces. By refactoring the code to use a Visitor [DP], no conditional logic is needed and the design becomes more flexible.