문제

내가 만든 상태계 및고 싶은 그것을 활용하는 제네릭에서 java.현재는지 볼 수 있는 방법이 작품을 만들고 고 코드입니다.이 디자인 문제에 접근해왔다 많은 시간 전에 임한 입력.heres 거친다.

class State { ... }

만 하나의 사본은 각각 별개의 주체(주로 익명의 클래스에 묶여 static final 변수)그것은 사용자 지정 데이터에 대한 각각의 상태에 있습니다.각 국가 객체에는 부모 상태(한 뿌리 상태)

class Message { ... } 

각각의 메시지가 별도로 만들어지고 각 사용자 지정 데이터가 있습니다.그들은 서브 클래스는니다.거기에 하나의 루트 메시지를 클래스입니다.

class Handler { ... } 

각각의 핸들러가 만든 한번만 찾으로 특정 국가/메시지 콤보입니다.

class StateMachine { ... }

현재의 추적을 유지 현재 상태와 모든 목록(State,Message) -> Handler 매핑됩니다.그것은 다른 기능을 뿐입니다.내가 노력을 계속 이 클래스 일반적이고 서브 클래스와 입력 매개변수로 사용상에서 나의 프로그램,그리고 각각의 시간과 다른 설정의 Message's/ State's/고 Handler's.다른 StateMachine's 것 서로 다른 매개변수를 자신의 처리기입니다.

접근

이 있는 상태 기계적 매핑됩니다.

class StateMachine<MH extends MessageHandler> {
  static class Delivery {
    final State state;
    final Class<? extends Message> msg;
  }
  HashMap<Delivery, MH> delegateTable;
  ...
}

class ServerStateMachine extends StateMachine<ServerMessageHandler> {
  ...
}

할 수 있는 사용자 정의 처리기 위한 방법 이 특정한 상태 기계입니다.에 대한 매개 변수 처리기입니다.프로세스 방법을 덮어쓸 수 있습니다.그러나 처리기할 수 없는 매개 변수가 있는 메시지에 의해 유형입니다.

문제: 이를 사용하는 것 instanceof 정신 확인에 대한 각각의 메시지 처리기는(그것은 확실히 메시지를 받고 그것이 기대하).

접근 B

로 만들 수 있습니다 각각의 메시지를 핸들러를 매개 변수가 있는 메시지 입력

class MessageHandler<M extends Message> {
  void process(M msg) { .... }
}

문제: 유형*삭제를 방지 나를 저장에서 이러한에서 좋은 hashmap 이후 모든 MessageHandler's 에 입력됩니다.는 경우에 저장할 수 있는 그들을 지도에서,내가 할 수 있 적이 그들을 그들에게 전화와 적절한 가지 인자가.

접근 C

이 있는 상태의 개체를 처리하는 모든 메시지입니다.

class State<M extends Message> { ... }
class ServerState<M extends ServerMessage> extends State<M> { ... }

나는 메시지 처리기에 묶여 특정 상태계국(의 안에 그들을 두),(각각의 인스턴스에 상태 기계 것이 자신의 목록의 유효한다)수 있는 처리기의 것에 특정 유형입니다.(서버 상태계->서버에 메시지 처리기).

문제: 각 국가만을 처리할 수 있 하나의 메시지는 유형입니다.당신은 또한 당신을 잃게 부모는 아이디어 국가의 처리할 수 있는 다른 메시지보다는 아이다.유형*삭제를 방지합 StateMachine 에서 호출하면 현재 미국 프로세스 방법이 있습니다.

접근 D

메시지의 과정에 자신을 기반으로 상태가 됩니다.

문제: 정말로 간주므로,각각의 메시지가 있어야 한 다른 처리기의 현재 상태를 기반으로 기계 상태가 됩니다.보낸 사람이 알 수 없습니다 현재 StateMachine's state.

E 접근법

에 대해 잊지 제네릭하고 하드 드 코드 상태 메시지 처리 가치 문입니다.

문제: 정신

안전 솔루션:

귀하의 의견을 주셔서 감사합니다 모두 나는 생각한 문제는 내가 줄어들지 않았이 좋은 문제(너무 많은 토론)heres 내가 지금입니다.

public class State { }

public class Message { }

public class MessageHandler<T extends Message> { }

public class Delivery<T extends Message> {
  final State state;
  final Class<T> msgClass;
}

public class Container {

  HashMap<Delivery<? extends Message>, MessageHandler<? extends Message>> table;

  public <T extends Message> add(State state, Class<T> msgClass, MessageHandler<T> handler) {
    table.put(new Delivery<T>(state, msgClass), handler);
  }

  public <T extends Message> MessageHandler<T> get(State state, T msg) {
    // UNSAFE - i cannot cast this properly, but the hashmap should be good
    MessageHandler<T> handler = (MessageHandler<T>)table.get(new Delivery<T>(state, msg.getClass()));
    return handler;
  }

}
도움이 되었습니까?

해결책

에 대한 접근 B,을 사용하지 않"좋은"hashmap.대신,쓰기,이종 형식이 안전한 컨테이너의 매핑 처리기 등 개체:

interface Handler<T extends Message> {
...}


interface Message {...}

interface HandlerContainer {

    <T extends Message> void register(Class<T> clazz, Handler<T> handler);

    <T extends Message> Handler<T> getHandler(T t);

}


class HandlerContainerImpl implements HandlerContainer {

    private final Map<Class<?>,Handler<?>> handlers = new HashMap<Class<?>,Handler<?>>();

    <T extends Message> void register(Class<T> clazz, Handler<T> handler) {
          if (clazz==null || handler==null) {
             throw new IllegalArgumentException();
          }
          handlers.put(clazz,handler);
    }

    //Type safety is assured by the register message and generic bounds
    @SuppressWarnings("unchecked")
    <T extends Message> Handler<T> getHandler(T t) {
            return  (Handler<T>)handlers.get(t.getClass());

    }

}

다른 팁

E 와 함께 열거를 나타내는 상태 메시지는 아마도 가장 쉬운 방법입니다.하지만 그것은 아주 확장할 수 있습니다.

C 를 사용하는 방문자가 본 상태에서 클래스 파견 유형 메시지처럼 수 있는 최고의 옵션이 있습니다.선택 사 instanceof 그리고 방문자,나는 생각하는 방문자가 약간 청소기(이기는 하지만 여전히 어색).유형 erasure 문제가 야기한 주목할만한 어려움 및 처리에 메시지가 보이 다소니다.일반적인 상태계 표기는 국가의 중심으로 제어합니다.또한,당신은 있을 수 있는 방문자가 추상 클래스는 메시지에 대한 유형에 오류가 발생에 모든 국가할 수 있으므국 오류가-가을에 잘못된 메시지를위한 무료입니다.

C+방문자 것이 매우 유사하는 방법을 자주 사용을 구현하는 경우 주 컴퓨터에서 C 언어로 첫 번째 클래스 기능-"상태"에 의해 표현된 함수 포인터를 처리하는 메시지 현재 상태에서,그와 함께 반환하는 함수 포인터를 다음 국가능(가능하게 자).국기 제어 루프 단지를 가져오는 다음 메시지를 전달하는 현재 상태,기능 및 업데이트의 개념"현재의"때 그것을 반환합니다.

접근 E.에 대해 잊지 제네릭 사용하고,인터페이스가 있습니다.

class Message { ... }
class State { ... }

class Machine {
  static State handle(State current, Message msg) {
    ...
  }
}

class CustomMessage extends Message { ... }
class CustomState extends State { ... }

class CustomMachine {
  static CustomState handle(CustomState current, CustomMessage msg) {
    // custom cases
    ...

    // default: generic case
    return Machine.handle(current, msg);
  }
}

접근 방식에서는 몇 가지 장소를 사용할 수 있습니다.일반 사용 POJO 클래스고에 주석을 처리할 수 있도록 관리자 입력 클래스를 실행하는 국기:

public class MyState {
 @OnEntry
 public void startStuff() {
  ...
 }

 @OnExit() 
 public void cleanup() {
  ..
 } 
}

거기에 몇 가지 개발의 구현,나는 생각한 과학적 도구 하나는 좋은 그러나 나는 오른쪽의 링크를 찾을 지금:http://mina.apache.org/introduction-to-mina-statemachine.html http://weblogs.java.net/blog/carcassi/archive/2007/02/finite_state_ma_1.html http://hubris.ucsd.edu/shared/manual.pdf

방법 F:

에 대해 잊지 제네릭지 않는 한 당신은 유형-특정 패턴이 있습니다.를 정의한 부부의 인터페이스는 당신이 원하는 시스템이 포함 아마도 같은 뭔가

interface StateMachineState<R extends StateMachineState,T> {
    /* returns next state */
    R execute(T otherState); 
}

그리고 특정 상태 기계,열거형 사용을 확장하는 StateMachineState:

class OtherState {
    public double x1;
    public int i;
}

enum MyState extends StateMachineState<MyState,OtherState>
{
    FOO {
       MyState execute(OtherState otherState) { 
           otherState.x1 += 3.0;
           otherState.i++;
           return BAR;
       }
    },
    BAR {
       MyState execute(OtherState otherState) { 
           otherState.x1 -= 1.0;
           otherState.i--;
           return (i % 3 == 0) ? FOO : BAR;
       }
    },         
}

다음을 할 수 있는 다음과 같습니다.

MyState state = MyState.FOO;
OtherState otherState = new OtherState();
otherState.i = 77;
otherState.x1 = 3.14159;
while (true)
{
    state = state.execute(otherState);
    /* do something else here */        
}

(주의:코드는지 확인하에 대한 구문 오류)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top