Java에서 일종의 이벤트 프레임 워크를 만드는 방법은 무엇입니까?

FinnTheHuman

GUI가 없습니다 (제 수업은 Minecraft Mod의 일부입니다). C # 이벤트 프레임 워크를 모방 할 수 있기를 원했습니다. 클래스는 이벤트를 선언하고 다른 사람들이 이벤트를 구독 할 수 있도록합니다.

내 첫 번째 접근 방식은라는 클래스 EventArgs를 만든 다음 다음과 같이하는 것이 었습니다 .

public class EventArgs
{
    public boolean handled;
}

@FunctionalInterface
public interface IEventHandler<TEvtArgs extends EventArgs>
{
    public void handle(Object source, TEvtArgs args);
}

public class Event<TEvtArgs extends EventArgs>
{
    private final Object owner;
    private final LinkedList<IEventHandler<TEvtArgs>> handlers = new LinkedList<>();

    public Event(Object owner)
    {
        this.owner = owner;
    }

    public void subscribe(IEventHandler<TEvtArgs> handler)
    {
        handlers.add(handler);
    }

    public void unsubscribe(IEventHandler<TEvtArgs> handler)
    {
        while(handlers.remove(handler));
    }

    public void raise(TEvtArgs args)
    {
        for(IEventHandler<TEvtArgs> handler : handlers)
        {
            handler.handle(owner, args);
            if(args.handled)
                break;
        }
    }
}

그런 다음 클래스는 다음과 같이 할 것입니다.

public class PropertyChangedEvtArgs extends EventArgs
{
    public final Object oldValue;
    public final Object newValue;

    public PropertyChangedEvtArgs(final Object oldValue, final Object newValue)
    {
        this.oldValue = oldValue;
        this.newValue = newValue;
    }
}

public class SomeEventPublisher
{
    private int property = 0;
    private final Random rnd = new Random();
    public final Event<PropertyChangedEvtArgs> PropertyChanged = new Event<>(this);

    public void raiseEventOrNot(int value)
    {
        if(rnd.nextBoolean())//just to represent the fact that the event is not always raised
        {
            int old = property;
            property = value;
            PropertyChanged.raise(new PropertyChangedEvtArgs("old(" + old + ")", "new(" + value + ")"));
        }                
    }
}

public class SomeSubscriber
{
    private final SomeEventPublisher eventPublisher = new SomeEventPublisher();

    public SomeSubscriber()
    {
        eventPublisher.PropertyChanged.subscribe(this::handlePropertyAChanges);
    }

    private void handlePropertyAChanges(Object source, PropertyChangedEvtArgs args)
    {
        System.out.println("old:" + args.oldValue);
        System.out.println("new:" + args.newValue + "\n");
    }

    public void someMethod(int i)
    {
        eventPublisher.raiseEventOrNot(i);
    }
}

public class Main
{
    private static final SomeSubscriber subscriber = new SomeSubscriber();

    public static void main(String[] args)
    {
        for(int i = 0; i < 10; ++i)
        {
            subscriber.someMethod(i);
        }
    }
}

이 순진한 접근 방식의 가장 큰 문제 raise는 공개적 으로 노출 하여 적절한 캡슐화를 깨뜨리는 것 입니다. 나는 그 주변의 길을 볼 수 없으며 아마도 내 전체 패턴이 잘못되었을 수 있습니다. 몇 가지 아이디어를 원합니다.

관련 문제도있다 : 나는 이벤트가 즉시 제기 할 싶습니다 그 수익을 올리는 방법. 스레드 또는 다른 구성을 사용하여 이것을 동기화하는 방법이 있습니까? 물론 호출자 코드는 동기화 작업에 포함될 수 없습니다. 완전히 투명해야합니다.

디모 414

여기서 가장 좋은 방법은 처음에 자체 이벤트 프레임 워크를 구현하지 않고 기존 라이브러리에 의존하는 것입니다. 기본적으로 Java는를 제공 EventListener하며 최소한 여기에 문서화 된 패턴을 따를 수 있습니다. 비 GUI 응용 프로그램의 경우에도이 조언의 대부분이 적용됩니다.

JDK Guava를 넘어 서면 정확한 사용 사례에 따라 몇 가지 가능한 옵션이 제공됩니다.

가장 가능성이 높은 후보는 다음 EventBus과 같습니다.

구성 요소가 서로 명시 적으로 등록 할 필요없이 (따라서 서로를 인식 할 필요없이) 구성 요소 간의 게시-구독 스타일 통신을 허용합니다.

또는 ListenableFuture(및 ListeningExecutorService) 다음 중 :

[에 제출 된 작업 Executor]이 완료되면 또는 계산이 이미 완료된 경우 즉시 실행할 콜백을 등록 할 수 있습니다 . 이 간단한 추가를 통해 기본 Future 인터페이스가 지원할 수없는 많은 작업을 효율적으로 지원할 수 있습니다.

또는 다음과 같은 ServiceAPI :

시작 및 중지 방법이있는 작동 상태의 개체를 나타냅니다. 예를 들어 웹 서버, RPC 서버 및 타이머는 서비스 인터페이스를 구현할 수 있습니다. 적절한 시작 및 종료 관리가 필요한 이와 같은 서비스의 상태를 관리하는 것은 특히 여러 스레드 또는 일정이 관련된 경우에는 사소한 일이 아닙니다.

이 API를 사용하면 리스너등록 하여 서비스의 상태 변경에 응답 할 수 있습니다.

이러한 옵션이 사용 사례에 직접 작동하지 않더라도 Guava의 소스 코드 에서 이벤트 기반 동작 및 에뮬레이션 할 수있는 리스너의 예를 살펴보십시오.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

엔티티 프레임 워크에서 테이블의 모든 레코드를 업데이트하는 방법은 무엇입니까?

분류에서Dev

핵심 PHP 프로젝트에서 yii 프레임 워크 프로젝트의 마스터 페이지를 사용하는 방법은 무엇입니까?

분류에서Dev

파이썬의 데이터 프레임 행 값에서 CSV를 만드는 방법은 무엇입니까?

분류에서Dev

이온 프레임 워크 + 각도에서 탭을 만드는 방법은 무엇입니까?

분류에서Dev

MVC / MVP 프레임 워크에서 단일 모델 / 컨트롤러와 연관되지 않은 페이지를 처리하는 방법은 무엇입니까?

분류에서Dev

로봇 프레임 워크 내에서 sikuli 스크립트를 실행하는 방법은 무엇입니까?

분류에서Dev

MediaCodec이 Android의 프레임 워크 내에서 코덱을 찾는 방법은 무엇입니까?

분류에서Dev

사진 프레임 워크-PHAsset에서 이미지의 CLLocation을 얻는 방법은 무엇입니까?

분류에서Dev

사진 프레임 워크-PHAsset에서 이미지의 CLLocation을 얻는 방법은 무엇입니까?

분류에서Dev

루프 엔티티 프레임 워크에서 데이터를 확인하는 방법은 무엇입니까?

분류에서Dev

Karate 프레임 워크에서 작은 오이 현지화를 사용하는 방법은 무엇입니까?

분류에서Dev

데이터 프레임에서 .csv 파일을 사용하여 삼자 네트워크를 구축하는 방법은 무엇입니까?

분류에서Dev

PHP 용 yii 프레임 워크의 cdbcache에서 종속성을 정의하는 방법은 무엇입니까?

분류에서Dev

기존 엔진없이 게임에서 EventTrigger의 프레임 워크를 디자인하는 방법은 무엇입니까?

분류에서Dev

로봇 프레임 워크에서 모든 텍스트를 얻는 방법은 무엇입니까?

분류에서Dev

라우팅 규칙에서 Yii 프레임 워크의 정적 페이지에 링크를 추가하는 방법은 무엇입니까?

분류에서Dev

Yii 프레임 워크에서 이름 대신 사용자 ID를 얻는 방법은 무엇입니까?

분류에서Dev

WordPress 테마 옵션에서 redux 프레임 워크를 사용하여 본문의 배경 이미지를 변경하는 방법은 무엇입니까?

분류에서Dev

Pandas 데이터 프레임에서 10k 레코드를 만드는 방법은 무엇입니까?

분류에서Dev

나중에 스칼라 플레이 프레임 워크 애플리케이션으로 데이터베이스를 만드는 방법은 무엇입니까?

분류에서Dev

로봇 프레임 워크에서 동일한 키워드로 하나의 테스트 케이스를 실행하는 경우 테스트 케이스 수를 2로 지정하는 방법은 무엇입니까?

분류에서Dev

코어 플롯 프레임 워크 Objective-C에서 도넛 차트를 만드는 방법은 무엇입니까?

분류에서Dev

Nest.js 프레임 워크에서 종속성 주입 컨테이너 만 사용하는 방법은 무엇입니까?

분류에서Dev

다른 프레임 워크의 명령 줄에서 dnx xunit 테스트를 실행하는 방법은 무엇입니까?

분류에서Dev

Yii 프레임 워크에 워드 프레스 프로젝트를 통합하는 방법은 무엇입니까?

분류에서Dev

헤더 검색 경로에서 두 개 이상의 프레임 워크를 사용하는 방법은 무엇입니까?

분류에서Dev

HAPI 프레임 워크의 후속 경로에서 인증이 완료되면 request.auth.isAuthenticated를 채우는 방법은 무엇입니까?

분류에서Dev

일괄 처리를 사용하여 네트워크 메인 프레임 용 여러 logs.txt를 만드는 방법은 무엇입니까?

분류에서Dev

파이썬 데이터 프레임에서 특정 월의 일 수를 제공하는 새 열을 만드는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    엔티티 프레임 워크에서 테이블의 모든 레코드를 업데이트하는 방법은 무엇입니까?

  2. 2

    핵심 PHP 프로젝트에서 yii 프레임 워크 프로젝트의 마스터 페이지를 사용하는 방법은 무엇입니까?

  3. 3

    파이썬의 데이터 프레임 행 값에서 CSV를 만드는 방법은 무엇입니까?

  4. 4

    이온 프레임 워크 + 각도에서 탭을 만드는 방법은 무엇입니까?

  5. 5

    MVC / MVP 프레임 워크에서 단일 모델 / 컨트롤러와 연관되지 않은 페이지를 처리하는 방법은 무엇입니까?

  6. 6

    로봇 프레임 워크 내에서 sikuli 스크립트를 실행하는 방법은 무엇입니까?

  7. 7

    MediaCodec이 Android의 프레임 워크 내에서 코덱을 찾는 방법은 무엇입니까?

  8. 8

    사진 프레임 워크-PHAsset에서 이미지의 CLLocation을 얻는 방법은 무엇입니까?

  9. 9

    사진 프레임 워크-PHAsset에서 이미지의 CLLocation을 얻는 방법은 무엇입니까?

  10. 10

    루프 엔티티 프레임 워크에서 데이터를 확인하는 방법은 무엇입니까?

  11. 11

    Karate 프레임 워크에서 작은 오이 현지화를 사용하는 방법은 무엇입니까?

  12. 12

    데이터 프레임에서 .csv 파일을 사용하여 삼자 네트워크를 구축하는 방법은 무엇입니까?

  13. 13

    PHP 용 yii 프레임 워크의 cdbcache에서 종속성을 정의하는 방법은 무엇입니까?

  14. 14

    기존 엔진없이 게임에서 EventTrigger의 프레임 워크를 디자인하는 방법은 무엇입니까?

  15. 15

    로봇 프레임 워크에서 모든 텍스트를 얻는 방법은 무엇입니까?

  16. 16

    라우팅 규칙에서 Yii 프레임 워크의 정적 페이지에 링크를 추가하는 방법은 무엇입니까?

  17. 17

    Yii 프레임 워크에서 이름 대신 사용자 ID를 얻는 방법은 무엇입니까?

  18. 18

    WordPress 테마 옵션에서 redux 프레임 워크를 사용하여 본문의 배경 이미지를 변경하는 방법은 무엇입니까?

  19. 19

    Pandas 데이터 프레임에서 10k 레코드를 만드는 방법은 무엇입니까?

  20. 20

    나중에 스칼라 플레이 프레임 워크 애플리케이션으로 데이터베이스를 만드는 방법은 무엇입니까?

  21. 21

    로봇 프레임 워크에서 동일한 키워드로 하나의 테스트 케이스를 실행하는 경우 테스트 케이스 수를 2로 지정하는 방법은 무엇입니까?

  22. 22

    코어 플롯 프레임 워크 Objective-C에서 도넛 차트를 만드는 방법은 무엇입니까?

  23. 23

    Nest.js 프레임 워크에서 종속성 주입 컨테이너 만 사용하는 방법은 무엇입니까?

  24. 24

    다른 프레임 워크의 명령 줄에서 dnx xunit 테스트를 실행하는 방법은 무엇입니까?

  25. 25

    Yii 프레임 워크에 워드 프레스 프로젝트를 통합하는 방법은 무엇입니까?

  26. 26

    헤더 검색 경로에서 두 개 이상의 프레임 워크를 사용하는 방법은 무엇입니까?

  27. 27

    HAPI 프레임 워크의 후속 경로에서 인증이 완료되면 request.auth.isAuthenticated를 채우는 방법은 무엇입니까?

  28. 28

    일괄 처리를 사용하여 네트워크 메인 프레임 용 여러 logs.txt를 만드는 방법은 무엇입니까?

  29. 29

    파이썬 데이터 프레임에서 특정 월의 일 수를 제공하는 새 열을 만드는 방법은 무엇입니까?

뜨겁다태그

보관