重载方法调用重新设计

时间:2012-04-25 06:40:04

标签: java

我有一个接口IAction,它有一个通用方法:

public interface IAction  {
    void doAction(ISignal sig, IState state);
}

然后另一个类IActionAbstract实现IAction接口并使用instanceof子句调用重载方法:

public abstract class IActionAbstract implements IAction
{

@Override
public void doAction(ISignal sig, IState state)
{
    if(sig instanceof ISignal1 && state instanceof IState1)
    {
        doOther((ISignal1)sig, (IState1)state);
    }       
    else if(sig instanceof ISignal2 && state instanceof IState1)
    {
        doOther((ISignal2)sig, (IState1)state);
    }
    else if(sig instanceof ISignal1 && state instanceof IState2)
    {
        doOther((ISignal1)sig, (IState2)state);
    }
}

abstract void doOther(ISignal1 sig, IState1 state);
abstract void doOther(ISignal2 sig, IState1 state);
abstract void doOther(ISignal1 sig, IState2 state);
}

我想删除instanceof检查并替换为泛型或重新设计,但不向IAction添加更多方法。我看到如何用反射做到这一点,但如果可能的话我想避免。

编辑:删除了泛型,因为它们不是必需的。我会尝试解释更多,以便更好地了解这种方法。可能会生成IActionAbstract文件,开发人员可以使用impl来实现这些方法。 ISignalIState一起使该方法独特,可以将其视为状态机状态和信号。

类的用法看起来像伪代码:

List<IAction> actions;
actions.get(i).doAction(ISignal1, IState1);
actions.get(i).doAction(ISignal2, IState2);
and so on...

2 个答案:

答案 0 :(得分:3)

在我看来,你想要单独实施IAction,即

// generic interface declaration
public interface IAction<T extends ISignal, S extends IState> {
    void doAction(T sig, S state);
}

// typed implementations of the generic interface
public class Action1 implements IAction<Signal1, State1> {
    doAction(Signal1 sig, State1 state) {
        // impl
    }
}

// another typed implementations of the generic interface
public class Action2 implements IAction<Signal2, State2> {
    doAction(Signal2 sig, State2 state) {
        // impl
    }
}

......等等。否则你甚至不使用泛型。

答案 1 :(得分:2)

我不太确定你在寻找什么。我同意@claesv的说法,你的方法可能没有必要。这是我的方法:

public class GenericsQuestion {
    public static void main(String[] args) {
        ISignal sig = new Signal1();
        IState state = new State1();

        Strategy.getStrategyForSignalAndState(sig.getClass(), state.getClass()).doOther(sig, state);
    }
}

class SignalAndState {
    private Class<? extends IState> state;
    private Class<? extends ISignal> signal;

    /**
     * 
     */
    public SignalAndState(Class<? extends ISignal> signal, Class<? extends IState> state2) {
        // save state and signal
    }
    // equals & hashcode
}

enum Strategy {
    ONE {
        @Override
        public void doOther(ISignal sig, IState state) {
        }
    },
    TWO {
        @Override
        public void doOther(ISignal sig, IState state) {
        }
    },
    THREE {
        @Override
        public void doOther(ISignal sig, IState state) {
        }
    };

    private static final Map<SignalAndState, Strategy> STRATEGIES = new HashMap<SignalAndState, Strategy>();
    static {
        STRATEGIES.put(new SignalAndState(Signal1.class, State1.class), ONE);
        STRATEGIES.put(new SignalAndState(Signal1.class, State2.class), TWO);
        STRATEGIES.put(new SignalAndState(Signal2.class, State1.class), THREE);
    }

    public static Strategy getStrategyForSignalAndState(Class<? extends ISignal> sig, Class<? extends IState> state) {
        return STRATEGIES.get(new SignalAndState(sig, state));
    }

    public abstract void doOther(ISignal sig, IState state);
}

我的眼睛,这比使用instanceof更优雅和灵活。

您可以通过使用EnumMap来改善这一点,但我没有那么多使用,并且不确定其好处和/或用法。如果您想进一步调查,只需提示一下。