What are the ways to eliminate the use of switch in code?
标签:
design-patterns
相关问题
- Name for a method that has only side effects
- What is a correct approach to manage test data usi
- Can a [GoF]-ConcreteSubject override the notify me
- Can the builder pattern ever be doing too much?
- Carry STRef implicitly in an environment during co
switch
statements would be good to replace if you find yourself adding new states or new behaviour to the statements:Adding new behaviour requires copying the
switch
, and adding new states means adding anothercase
to everyswitch
statement.In Java, you can only switch a very limited number of primitive types whose values you know at runtime. This presents a problem in and of itself: states are being represented as magic numbers or characters.
Pattern matching, and multiple
if - else
blocks can be used, though really have the same problems when adding new behaviours and new states.The solution which others have suggested as "polymorphism" is an instance of the State pattern:
Replace each of the states with its own class. Each behaviour has its own method on the class:
Each time you add a new state, you have to add a new implementation of the
IState
interface. In aswitch
world, you'd be adding acase
to eachswitch
.Each time you add a new behaviour, you need to add a new method to the
IState
interface, and each of the implementations. This is the same burden as before, though now the compiler will check that you have implementations of the new behaviour on each pre-existing state.Others have said already, that this may be too heavyweight, so of course there is a point you reach where you move from one to another. Personally, the second time I write a switch is the point at which I refactor.
The most obvious, language independent, answer is to use a series of 'if'.
If the language you are using has function pointers (C) or has functions that are 1st class values (Lua) you may achieve results similar to a "switch" using an array (or a list) of (pointers to) functions.
You should be more specific on the language if you want better answers.
Function pointers are one way to replace a huge chunky switch statement, they are especially good in languages where you can capture functions by their names and make stuff with them.
Of course, you ought not force switch statements out of your code, and there always is a chance you are doing it all wrong, which results with stupid redundant pieces of code. (This is unavoidable sometimes, but a good language should allow you to remove redundancy while staying clean.)
This is a great divide&conquer example:
Say you have an interpreter of some sort.
Instead, you can use this:
Note that I don't know how to remove the redundancy of the opcode_table in C. Perhaps I should make a question about it. :)
Switch is not a good way to go as it breaks the Open Close Principal. This is how I do it.
And here is how to use it (taking your code):
Basically what we are doing is delegating the responsibility to the child class instead of having the parent decide what to do with children.
You might also want to read up on "Liskov Substitution Principle".
'switch' is just a language construct and all language constructs can be thought of as tools to get a job done. As with real tools, some tools are better suited to one task than another (you wouldn't use a sledge hammer to put up a picture hook). The important part is how 'getting the job done' is defined. Does it need to be maintainable, does it need to be fast, does it need to scale, does it need to be extendable and so on.
At each point in the programming process there are usually a range of constructs and patterns that can be used: a switch, an if-else-if sequence, virtual functions, jump tables, maps with function pointers and so on. With experience a programmer will instinctively know the right tool to use for a given situation.
It must be assumed that anyone maintaining or reviewing code is at least as skilled as the original author so that any construct can be safely used.
In a procedural language, like C, then switch will be better than any of the alternatives.
In an object-oriented language, then there are almost always other alternatives available that better utilise the object structure, particularly polymorphism.
The problem with switch statements arises when several very similar switch blocks occur at multiple places in the application, and support for a new value needs to be added. It is pretty common for a developer to forget to add support for the new value to one of the switch blocks scattered around the application.
With polymorphism, then a new class replaces the new value, and the new behaviour is added as part of adding the new class. Behaviour at these switch points is then either inherited from the superclass, overridden to provide new behaviour, or implemented to avoid a compiler error when the super method is abstract.
Where there is no obvious polymorphism going on, it can be well worth implementing the Strategy pattern.
But if your alternative is a big IF ... THEN ... ELSE block, then forget it.