4

IAction私は1つのジェネリックメソッドを持つインターフェースを持っています:

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を作成して生成される場合があります。 ISignalそしてIState一緒にメソッドをユニークにし、ステートマシンの状態と信号と考えることができます。

クラスの使用法は、擬似コードのようになります。

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

2 に答える 2

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
    }
}

...等々。それ以外の場合は、ジェネリックを使用していません。

于 2012-04-25T06:47:00.120 に答える
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を使用することでこれを改善できる可能性がありますが、私はそれほど多くは使用しておらず、利点や使用法についてはよくわかりません。さらに調査したい場合のヒントです。

于 2012-04-25T08:05:18.500 に答える