Refactor if statement to use appropriate pattern
I have an enum with some states in it:
enum State
{
A,
B,
C,
D
}
and an object that has a corresponding state:
class MyObject
{
State state;
}
I need to write an algorithm that takes two MyObject instances and does something depending on the particular states of those instances:
void doWork(MyObject o1, MyObject o2)
{
if (o1.state == A && o2.state == A)
{
// do something
}
else if (o1.state == A && o2.state == B)
{}
// etc for all combinations...
}
Obviously this approach has many problems and I would like to change it to ideally get rid of the if/else statement.
Is there any pattern for such a requirement?
Thanks
What you could do, although I'm not sure it would be that much better, is some kind of matrix of all possible combinations of two state
values; you could then use o1.state
and o2.state
as indexes into that matrix.
You could store different things in that matrix:
switch
block which would replace your if .. else if .. else
blocks -- not much of an improvement, really. Or your matrix could contain...
If you really want to get rid of the if
statements, that second option might be the better one; do take note, however, that your code will then no longer be close together in one location, as would be the case with if
/ switch
blocks, but spread over several different command objects/classes.
// forgive my syntax errors etc., my Java has definitely gone a little rusty!
interface WorkCommand {
public abstract void run(MyObject o1, MyObject o2);
}
...
Map<Pair<State,State>, WorkCommand> commands;
// ^ pseudo-code type for your command look-up map; type Pair<X,Y> doesn't exist,
// so replace this with something sensible!
void doWork(MyObject o1, MyObject o2)
{
WorkCommand worker = commands.get(new Pair<State,State>(o1, o2));
worker.run(o1, o2);
}
One way you can structure this, is you can have an abstract method in your enum which each element would implement:
enum State
{
A{
public void void doSomeWork(State state){
switch(state){
case A:
case B:
...
}
}
},
B,
C,
D
abstract void doSomeWork(State state);
}
Then your method can look like
void doWork(MyObject o1, MyObject o2){
o1.state.doSomeWork(o2.state);
}
Yes, it is called the... state pattern. The important thing is to only have one state for which to define behavior, ie you may need to combine your object1.state and object2.state into a meta-state. Register this meta-state with a statecontext so that when Myobject.state changes the meta-state is updated.
interface MyObjectStates {
void doWork(MyObject o1, MyObject o2);
}
class MyObjectStatesAA implements MyObjectStates {
void doWork(MyObject o1, MyObject o2) {
// do dowork for both states A
}
class MyObjectStatesBB implements MyObjectStates {
void doWork(MyObject o1, MyObject o2) {
// do dowork for both states B
}
// etc
You then need to hold one MyObjectStates object in a statecontext and update it when a MyObject.state is changed. You may even be able to remove the state enum alltogether. If this approach sounds interesting to you give me a note and I elaborate if you like.
The state pattern has the advantage that you don't need to save and read back an enum and chose a different codepath accordingly, but instead you provide separate code with every state you want to handle differently.
链接地址: http://www.djcxy.com/p/91844.html上一篇: 如何在if条件中避免NullPointerException
下一篇: 重构if语句以使用适当的模式