Java 中的多态调度

2022-09-03 14:20:53

在下文中,我希望 EventHandler 以一种方式处理 EventA,以另一种方式处理 EventB,以及任何其他事件(EventC、EventD) 以另一种方式处理。EventReceiver 仅接收对 Event 的引用并调用 EventHandler.handle()。当然,总是被调用的版本是EventHandler.handle(Event event)。

如果不使用 instanceOf,有没有办法多态调度(可能通过 EventHandler 或泛型中的另一种方法)到适当的句柄方法?

class EventA extends Event {
}

class EventB extends Event {
}

class EventC extends Event {
}

class EventD extends Event {
}

class EventHandler {
    void handle(EventA event) {
       System.out.println("Handling EventA");
    }

    void handle(EventB event) {
       System.out.println("Handling EventB");
    }

    void handle(Event event) {
       System.out.println("Handling Event");
    }
}

class EventReceiver {
    private EventHandler handler;

    void receive(Event event) {
        handler.handle(event);
    }
}    

答案 1

听起来像是应用访客模式(其变体)的案例。(在主流的OO语言中,如C++,C#和Java,方法是单调度的,即一次只能在一个类型上多态。访客允许一个实现双重调度

但是,这要求您也能够修改类,并创建从 s 到(的基本接口)的依赖项。EventEventEventHandler

class EventA extends Event {
  public handleBy(EventHandler eh) {
    eh.handleEventA(this);
  }
}

class EventB extends Event {
  public handleBy(EventHandler eh) {
    eh.handleEventB(this);
  }
}

class EventHandler {
    void handleEventA(EventA event) {
       System.out.println("Handling EventA");
    }

    void handleEventB(EventB event) {
       System.out.println("Handling EventB");
    }

    void handle(Event event) {
       event.handleBy(this);
    }
}

答案 2

这是双重调度的用例,没有(人们可能确实知道它被称为访问者)?我将仅针对事件 A 实现您的示例

class Event {
    /**
     * Will do some type escalation
     */
    void handleWith(EventHandler care) {
        care.handle(this);
    }
}



class EventA extends Event {
    /**
     * As event is EventA, this implementation is called, with its correct type forced by the cast
     */
    void handleWith(EventHandler care) {
        care.handle((EventA) this);
    }
}

class EventHandler {
    /**
     * Finally comes here
     */
    void handle(EventA event) {
       System.out.println("Handling EventA");
    }

    void handle(EventB event) {
       System.out.println("Handling EventB");
    }

    void handle(Event event) {
       System.out.println("Handling Event");
    }

    /**
     * Go here first and dispatch call to Event class
     */
    void doHandle(Event event) {
        event.handleWith(this);
    }
}

class EventReceiver {
    private EventHandler handler;

    void receive(Event event) {
        handler.doHandle(event);
    }
}    

推荐