Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中无instanceof或getClass()的动态分派_Java_Design Patterns_Instanceof_Dynamic Dispatch - Fatal编程技术网

Java中无instanceof或getClass()的动态分派

Java中无instanceof或getClass()的动态分派,java,design-patterns,instanceof,dynamic-dispatch,Java,Design Patterns,Instanceof,Dynamic Dispatch,我有以下域对象: public interface Event {} public class FirstEvent {} public class SecondEvent {} 然后我有另一个模块,它应该和我的域对象完全解耦,这意味着它知道域对象,但域对象不应该知道这个附加模块的存在 在这个模块中,我通过公共接口事件接收对象,我需要根据特定的事件类型采取不同的行动 目前,我的代码如下所示: if (event instanceof FirstEvent.class) {

我有以下域对象:

public interface Event {}    
public class FirstEvent {}    
public class SecondEvent {}
然后我有另一个模块,它应该和我的域对象完全解耦,这意味着它知道域对象,但域对象不应该知道这个附加模块的存在

在这个模块中,我通过公共接口
事件
接收对象,我需要根据特定的事件类型采取不同的行动

目前,我的代码如下所示:

if (event instanceof FirstEvent.class) {
    doFirst();
}
else if (event instanceof SecondEvent.class) {
    doSecond();
}
它工作得很好,但是静态分析工具和代码审阅者抱怨我不应该使用
instanceof
,我应该用更面向对象的方法来代替它。反射或
getClass()
也不是选项

在Java中如何做到这一点


我已经回顾了许多关于替换
instanceof
的现有问题,但所有这些问题都建议直接在域对象中添加一些逻辑。但是,在这种情况下,我不想用特定于我的模块的逻辑来污染它们。

访客模式,也称为双重分派,在这里通常很有用

接口是用每个已知事件类型的方法定义的,每个事件实现一个接口方法,该接口方法允许外部对象通过该接口的实现调用它。然后,该事件确保使用自己的“this”引用调用接口的特定于类型的方法,这样就不会得到任何显式向下转换

public interface EventVisitor  {
    visit(FirstEvent firstEvent);
    visit(SecondEvent secondEvent);
}

public class FirstEvent {
    ...
    public void allowVisit(EventVisitor ev) {
        ev.visit(this); // calls the 'FirstEvent' overriden method
    }
    ...
}


public class SecondEvent {
    ...
    public void allowVisit(EventVisitor ev) {
        ev.visit(this); // calls the 'SecondEvent' overriden method
    }
    ... 
}

public class MyOtherObject implements EventVisitor, EventListener {
   ...
   public void signalEvent(Event e) {
       e.allowVisit(this);
   }

   public void visit(FirstEvent e) {
       // handle FirstEvent type
   }

   public void visit(SecondEvent e) {
       // handle SecondEvent type
   }
}


这种类型的缺点是很难添加新的事件类型,因为EventListener接口必须枚举它们。你可以用一种“包罗万象”的方法来解决这个问题,但是它很混乱,而且仍然很难升级。

排除
反射是可以理解的,但是使用
getClass()
不应该是问题

我处理此问题的解决方案:

import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class DynamicDispatch{
    Map<String,Event> events = new ConcurrentHashMap<String,Event>();
    public DynamicDispatch(){
        Event event = new FirstEvent();
        events.put(event.getName(),event);
        event = new SecondEvent();
        events.put(event.getName(),event);
    }
    public Event getEvent(String eventName){
        return events.get(eventName);
    }
    public static void main(String args[]){
        DynamicDispatch dispatchObj = new DynamicDispatch();
        Event event = dispatchObj.getEvent(args[0]);
        System.out.println("dispatchObj:"+event+":"+event.getName());
    }
}

interface Event {
    public String getName();
}
class FirstEvent implements Event{
    public String getName(){
        //return this.getClass().getSimpleName();
        return "FirstEvent";
    }
}
class SecondEvent implements Event{
    public String getName(){
        //return this.getClass().getSimpleName();
        return "SecondEvent";
    }
}
我仍然喜欢使用
返回这个.getClass().getSimpleName()而不是对值进行硬编码


我希望上面的代码可以使用
静态分析工具

为什么不能从
事件
中实现
第一个事件
第二个事件
,然后调用该方法?我认为没有第三种选择。99%的情况下,我同意代码审阅者的意见,即您应该使用继承而不是
instanceof
getClass
,但也有例外情况。@DeendayalGarg不确定我是否理解您的问题
FirstEvent
SecondEvent
已经在另一个模块中实现了。@PaulBoddington这对我来说也是一个正确的答案,至少在他们开始抱怨时,在代码审查期间我会有一些支持我的东西。访客模式呢?
java DynamicDispatch FirstEvent
dispatchObj:FirstEvent@72d86c58:FirstEvent

java DynamicDispatch SecondEvent
dispatchObj:SecondEvent@72d86c58:SecondEvent