2011-01-09 1 views
0

간단한 큐 기반 시스템을 사용하여 여러 액터에 발생하는 이벤트를 관리하는 시스템이 있습니다. Event은 시간과 추상적 인 메소드 fire()을 가진 간단한 클래스입니다. Actorthink()act()의 두 가지 방법을 구현하는 간단한 인터페이스입니다. 반면,자바 디자인 패턴 : 이벤트 시스템, 특정 액터에 대한 복수 액션

public class ActorThinkEvent extends Event { 
    private Actor actor; 

    public ActorThinkEvent(Actor actor, long time) { 
     super(time); 
     this.actor = actor; 
    } 

    public void fire() { 
     Main.game.queue.add(actor.think()); 
    } 
}
public abstract class ActorActEvent extends Event { 
    protected Actor actor; 

    protected ActorActEvent(Actor actor, long time) { 
     super(time); 
     this.actor = actor; 
    } 

    public void fire() { 
     long spent = act(); 
     Main.game.queue.add(new ActorThinkEvent(actor, time + spent)); 
    } 

    public abstract long act(); 
} 

이 방법을 호출 글로벌 큐에 추가 할 것 인 ActorActEvent를 생성 해, 고정 "생각"각 배우처럼 구현이 기본 이벤트를 가지고 "연기"호출은 액션을 구현하는 커스텀 ActorActEvent 기반 클래스를 사용하여 수행 한 시간을 반환하고 새로운 "think"이벤트가 자동으로 큐에 추가됩니다.

는 는 는

내가 여기에서 볼 문제는 ActorActEvent 기반 클래스의 구현은 미리 저장된 인수 Actor 클래스의 몇 가지 방법 ActorActEvent.act()에서 간단한 위임 내려 오는 것입니다, 즉, 내 모든 ActEvent 클래스는 매우 유사 :

public class ActorMoveEvent extends ActorActEvent { 
    private Coords delta; 

    public ActorMoveEvent(Actor actor, long time, Coords delta) { 
     super(actor, time); 
     this.delta = delta; 
    } 

    public long act() { 
     return actor.moveBy(delta); 
    } 
}
public class ActorReloadEvent extends ActorActEvent { 
    public ActorReloadEvent(Actor actor, long time) { 
     super(actor, time); 
    } 

    public long act() { 
     return actor.reload(); 
    } 
}
public class ActorPickupEvent extends ActorActEvent { 
    private ItemStash wantedItems; 

    public ActorPickupEvent(Actor actor, long time, ItemStash wantedItems) { 
     super(actor, time); 
     this.wantedItems = wantedItems; 
    } 

    public long act() { 
     return actor.pickupItems(wantedItems); 
    } 
}

수십 개의 클래스로 끝날 수도 있습니다. 올바르게 이해하면 Command pattern의 기본 구현입니다. 그러나 모든 위임 클래스에 대해 기분이 좋지 않으며 특히 수동으로 작성하는 것이 좋습니다.

나는 그러나, 그것은 상당히 느린 것, 일반적인 ActorActEvent 클래스에 인수를 Method 인스턴스를 전달하고 미리 저장된하면서, Method.invoke() 같은 자바의 반사와 재료를 사용하여 생각했다. 나는이 모든 수업에 대해 발전기를 쓰려고 생각했지만, 그것은 나에게 상당히 서투른 해결책처럼 보인다.

일부 현대적인 스크립팅/기능적 언어라면, 블록/클로저와 같은 구조를 사용하여 끝내고, 먼저 준비하고 시간이되면 호출합니다. 아아, 나는 자바에서 효율적으로 만드는 법을 모른다.

상황을 개선하기 위해 무엇을 할 수 있습니까?

답변

1

나의 충고는 반사 경로를 내려가는 것입니다. 이 경우 "상당히 느릴 것"이라고 생각하는 것은시기 상조입니다. 리플렉션의 성능은 지난 10 년 동안 꽤 괜찮 았으며, Method 개 개체를 캐싱하여 이름을 재분석하는 데 걸리는 시간을 절약 할 수 있습니다 (이는 아마도 가장 큰 성능 적중입니다). 이 접근 방식은 유연하고 신속하게 구현할 수 있습니다.

클로저가 정말 마음에 들면 이벤트에 익명의 내부 클래스를 실험 해 볼 수 있습니다. 몇 가지 제한이 있습니다. 즉, 메소드를 좀 더 장황하게 표시해야하므로, 내부 클래스에서 변수에 액세스하려면 변수를 final로 선언해야합니다. 이 방법을 사용하면 정적 유형의 모든 성능과 안전성을 얻을 수 있지만 각 이벤트에 대한 클래스가 있어야합니다.

역사적으로 이벤트는 '세계 최악의 행동'을 나타내며 Object을 거쳤으며 대상을 대상으로 캐스트하고 처리하는 방법을 알고있었습니다.