문제

내 Java 게임 서버의 경우 패킷의 작업 ID를 기본적으로 서버에게 알리는 패킷의 용도를 전송합니다. 각 액션 ID (정수)를 함수에 매핑하고 싶습니다. 스위치를 사용하지 않고이 작업을 수행하는 방법이 있습니까?

도움이 되었습니까?

해결책

이건 어때?

HashMap<Integer, Runnable> map = new HashMap<Integer, Runnable>();
map.put(Register.ID, new Runnable() { 
    public void run() { functionA(); }
});
map.put(NotifyMessage.ID, new Runnable() { 
    public void run() { functionB(); }
});
// ...
map.get(id).run();

(일부 인수를 전달 해야하는 경우 적절한 매개 변수가있는 함수로 자신의 인터페이스를 정의하고 실행 가능한 대신 사용하십시오).

다른 팁

Java에는 실제로 기능 포인터가 없습니다 (대신 익명의 내부 수업을 받았습니다). 유형이 아닌 값을 켜는 한 스위치를 사용하는 데 아무런 문제가 없습니다. 스위치를 사용하고 싶지 않은 이유가 있습니까? 코드 어딘가에 액션 ID와 액션 사이에 매핑을 해야하는 것 같습니다. 왜 간단하게 유지하지 않겠습니까?

Java에는 일류 기능 포인터가 없습니다. 유사한 기능을 달성하려면 인터페이스를 정의하고 구현해야합니다. 익명의 내부 클래스를 사용하여 쉽게 사용할 수 있지만 여전히 예쁘지는 않습니다. 예는 다음과 같습니다.

public interface PacketProcessor
{
    public void processPacket(Packet packet);
}

...

PacketProcessor doThing1 = new PacketProcessor()
{
    public void processPacket(Packet packet)
    {
        // do thing 1
    }
};
// etc.

// Now doThing1, doThing2 can be used like function pointers for a function taking a
// Packet and returning void

Swing/AWT를 사용한 적이 있습니까? 그들의 이벤트 계층 구조는 비슷한 문제를 해결합니다. Java가 기능을 통과하는 방식은 예를 들어 인터페이스와 관련이 있습니다.

public interface ActionHandler {
    public void actionPerformed(ActionArgs e);
}

그런 다음 정수를이 개체에 매핑하려면 다음과 같은 것을 사용할 수 있습니다. java.util.HashMap<Integer,ActionHandler> 그것을 관리합니다. 실제 구현은 익명의 클래스 (Java의 "Lambda"에 대한 최상의 근사치) 또는 어딘가에 적절한 클래스로 이동할 수 있습니다. 익명의 수업 방법은 다음과 같습니다.

HashMap<Integer,ActionHandler> handlers;
handlers.put(ACTION_FROB, new ActionHandler() {
    public void actionPerformed(ActionArgs e) {
        // Do stuff
        // Note that any outer variables you intend to close over must be final.
    }
});
handlers.get(ACTION_FROB).actionPerformed(foo);

(편집) 더 학대하려면 해시 맵을 초기화 할 수 있습니다.

HashMap<Integer,String> m = new HashMap<Integer,String>() {{
    put(0,"hello");
    put(1,"world");
}};

예,하지만 인터페이스를 사용하면 각 콜백에 대한 인터페이스를 만들어야합니다. 즉, 전달하려는 모든 함수를 의미합니다. 이것을 처리하기 위해 대의원 클래스를 만들면 (진정한 기능 포인터가 아님) 통과 할 함수는 전달 될 수 있으며, 일반적인 반환 유형이되도록 일반적인 것을 남용하면 병목 현상을 거의 아무것도 줄이지 않아도됩니다.

C# delegate (MulticastDelegate가 정확)는 MethodInfo를 사용하여 java.lang.reflect.method를 사용하여 대의원 클래스에해야 할 일과 동일한 정보를 가져옵니다. 이 사이트의 다른 형태 에이 사이트의 다른 형태 에이 사이트의 코드를 게시했습니다. (예) C ++에서 온 함수를 전달하는 더 나은 방법이 필요하기 때문에 (특히 void) 기능에 대한 인터페이스를 만들어야하기 때문입니다. 이제 매개 변수 정보를 채우는 기능을 선택할 수 있습니다. Voila '! JIT 또는 JVM의 속도가 눈에 띄게 잃어버린 상태로 멋지고 사용할 수 있습니다. 그리고 만약 내가 일주일 동안 만 Java 프로그래밍을 배우고 있다면, 모든 Java 프로그래머가 그것을 할 수 있습니다.

또한 기본 리스너와 기본 인터페이스를 만들 때 리스너를 전달할 때 매우 잘 작동합니다. 함수의 이름이 변경되었으므로 더 이상 다른 청취자를 쓸 필요가 없습니다. 대의원 수업을 만드는 것은 매우 유용하고 통과 할 수있는 큰 장점이 있습니다.

정적 메소드를 인터페이스 할 수 있습니다. 이 방법을 사용하면 매개 변수도 지정할 수 있습니다. 인터페이스를 선언 ...

public interface RouteHandler {
    void handleRequest(HttpExchange t) throws IOException;
}

그리고 당신의지도 ...

private Map<String, RouteHandler> routes = new HashMap<>();

그런 다음 인터페이스/매개 변수와 일치하는 정적 메소드를 구현합니다 ...

public static void notFound(HttpExchange t) throws IOException {
    String response = "Not Found";

    t.sendResponseHeaders(404, response.length());
    OutputStream os = t.getResponseBody();
    os.write(response.getBytes());
    os.close();
}

그런 다음 해당 메소드를지도에 추가 할 수 있습니다 ...

routes.put("/foo", CoreRoutes::notFound);

그리고 그것들을 다음과 같이 부릅니다 ...

RouteHandler handler = routes.get("/foo");
handler.handleRequest(exchange);

또 다른 유사한 aproach는 Java 8의 공급 업체를 사용할 수 있습니다.

Map<Integer, Supplier<T> suppliers = new HashMap();
suppliers.put(1, () -> methodOne());
suppliers.put(2, () -> methodTwo());

// ...

public T methodOne() { ... }
public T methodTwo() { ... }

// ...

T obj = suppliers.get(id).run();

책임 패턴의 체인을 사용하여이를 수행 할 수 있습니다.

다른 개체를 연결된 목록과 같은 종류와 함께 연결하는 패턴입니다. 즉, 각 객체는 체인에서 다음을 참조합니다. 체인의 물체는 일반적으로 하나의 특정 동작을 처리합니다. 객체 사이의 흐름은 스위치 케이스 문과 매우 유사합니다.

논리를 널리 알리고 과도하게 긴 체인이 성능 문제를 일으킬 수있는 것과 같은 일부 gotchas가 있습니다. 그러나이 gotchas와 함께 당신은 시험 성이 높아지고 응집력이 강한 이점이 있습니다. 또한 분기의 트리거로 사용 열거, 바이트, int 쇼트 및 숯 표현에 국한되지 않습니다.

Lambdaj Library에서 폐쇄를 구현 한 방법을 확인하십시오. 그들은 실제로 C# 대표와 매우 유사한 행동을 가지고 있습니다.

http://code.google.com/p/lambdaj/wiki/closures

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