Java 用更通用的方法替换elseif

Java 用更通用的方法替换elseif,java,if-statement,switch-statement,Java,If Statement,Switch Statement,我有一段代码: @Override public void inform(String data) { if (data.equals(C.SubscriptionEvents.WINDOW_CLOSED)) { File tempFolder = new File("temp"); File[] files = tempFolder.listFiles(); if (files != null) { for (Fi

我有一段代码:

@Override
public void inform(String data) {
    if (data.equals(C.SubscriptionEvents.WINDOW_CLOSED)) {
        File tempFolder = new File("temp");
        File[] files = tempFolder.listFiles();
        if (files != null) {
            for (File f : files) f.delete();
        }
    } else if (data.equals(C.Controller.Commands.SELECT_MODE_VERTICES)) {
        MainModel.setCurrentMode(Mode.VERTICES);
        display.getInfoSection().repaint();
    } else if (data.equals(C.Controller.Commands.SELECT_MODE_LINES)) {
        MainModel.setCurrentMode(Mode.LINES);
        display.getInfoSection().repaint();
    } else if (data.equals(C.Controller.Commands.SELECT_MODE_SECTORS)) {
        MainModel.setCurrentMode(Mode.SECTORS);
        display.getInfoSection().repaint();
    }
}
该方法获取一个字符串,该字符串是命令名。根据名称,它执行指定的行为。正如您所看到的,它开始有太多的其他功能(并且可能会有更多)。此方法属于包之间共享的接口,因此我决定将参数设置为字符串。
有没有更好的方法来避免在有大量命令(这也包括switch case)时方法过于庞大?

您可以检查
命令
模式,但它可能需要相当广泛的重构,并使方法
通知()
接受类型为
命令的对象

如何使用
Enum
而不是
if…else

enum Event {
    NULL(null, context -> { }),
    WINDOWS_CLOSE(C.SubscriptionEvents.WINDOW_CLOSED, context -> {
        File tempFolder = new File("temp");
        File[] files = tempFolder.listFiles();
        if (files != null) {
            for (File f : files) f.delete();
        }
    }),
    SELECT_MODE_VERTICES(C.Controller.Commands.SELECT_MODE_VERTICES, context -> {
        MainModel.setCurrentMode(Mode.VERTICES);
        display.getInfoSection().repaint();
    }),
    SELECT_MODE_LINES(C.Controller.Commands.SELECT_MODE_VERTICES, context -> {
        MainModel.setCurrentMode(Mode.LINES);
        display.getInfoSection().repaint();
    }),
    SELECT_MODE_SECTORS(C.Controller.Commands.SELECT_MODE_SECTORS, context -> {
        MainModel.setCurrentMode(Mode.SECTORS);
        display.getInfoSection().repaint();
    });

    private final String id;
    private final Consumer<Foo> consumer;

    Event(String id, Consumer<Foo> consumer) {
        this.id = id;
        this.consumer = consumer;
    }

    public final void accept(Foo context) {
        consumer.accept(context);
    }

    public static Event selectEvent(String data) {
        for (Event event : values())
            if (event.id.equals(data))
                return event;
        return NULL;
    }
}

可以使用枚举类,如下所示:

public enum Command {
    WINDOW_CLOSED { //C.SubscriptionEvents.WINDOW_CLOSED
        public void invoke() {
            File tempFolder = new File("temp");
            File[] files = tempFolder.listFiles();
            if (files != null) {
                for (File f : files) f.delete();
            }
        }
    }
    ,SELECT_MODE_VERTICES { // C.Controller.Commands.SELECT_MODE_VERTICES
        public void invoke() {
            MainModel.setCurrentMode(Mode.VERTICES);
            display.getInfoSection().repaint();
        }
    }
    ,SELECT_MODE_LINES { // C.Controller.Commands.SELECT_MODE_LINES
        public void invoke() {
            MainModel.setCurrentMode(Mode.LINES);
            display.getInfoSection().repaint();
        }
    }
    ,SELECT_MODE_SECTORS { // C.Controller.Commands.SELECT_MODE_SECTORS
        public void invoke() {
            MainModel.setCurrentMode(Mode.SECTORS);
            display.getInfoSection().repaint();
        }
    }
    ;
    public abstract void invoke();
}
然后用以下内容替换上述功能的核心:

@Override
public void inform(String data) {
    Command.valueOf(data).invoke();
}

“枚举”值的名称必须与您在原始代码中测试的各种内容的字符串值完全匹配(例如C.SubscriptionEvents.WINDOW\u CLOSED、C.SubscriptionEvents.WINDOW\u CLOSED)

您可以通过这种方式简化它

@Override
public void inform(String data) {
    Map<String, String> map = new HashMap<String, int>();
    map.put(C.Controller.Commands.SELECT_MODE_VERTICES, Mode.VERTICES);
    map.put(C.Controller.Commands.SELECT_MODE_LINES), Mode.LINES);
    map.put(C.Controller.Commands.SELECT_MODE_SECTORS, Mode.SECTORS);
    if (data.equals(C.SubscriptionEvents.WINDOW_CLOSED)) {
        File tempFolder = new File("temp");
        File[] files = tempFolder.listFiles();
        if (files != null) {
            for (File f : files) f.delete();
        }
    } else if (map.containsKey(data)) {
        MainModel.setCurrentMode(map.get(key));
        display.getInfoSection().repaint();
    } 
}
@覆盖
公共无效通知(字符串数据){
Map Map=newhashmap();
map.put(C.Controller.Commands.SELECT\u MODE\u顶点,MODE.VERTICES);
map.put(C.Controller.Commands.SELECT\u MODE\u line)、MODE.line);
map.put(C.Controller.Commands.SELECT_MODE_SECTORS,MODE.SECTORS);
if(数据等于(C.SubscriptionEvents.WINDOW_CLOSED)){
File tempFolder=新文件(“temp”);
File[]files=tempFolder.listFiles();
如果(文件!=null){
对于(文件f:files)f.delete();
}
}else if(地图容器(数据)){
MainModel.setCurrentMode(map.get(key));
display.getInfoSection().repaint();
} 
}

switch case如何?很抱歉,我也忘了提到switch case-我的意思是,当它达到一个具有大量命令的点时,没有一种方法不会使函数变得巨大。您可以将命令建模为一个单独的类,共享一个公共接口,并将行为放入该类实现中。这就是Ivan的答案所推荐的“命令模式”。也许这个问题可以提供一个解决方案:另外:可以通过使命令实例成为内部类(甚至是枚举)的一部分并将其放入映射结构来限制重构的范围。那么inform-mathod的签名就不需要更改了。如果我的视图是调用调用调用的视图,但它位于不同的包(甚至是jar)中,我如何使用它呢?视图只知道命令的名称(甚至对于每个命令都可以使用枚举)。控制器用名称接收此命令请求,并且应该知道根据给定名称实例化哪个命令-控制器如何知道没有长的elseif/switch?@GadWissberg您的控制器将只执行
invoke(command c){c.execute();}
命令
对象将在其他位置创建,但我似乎不明白方法对象本身将在何处实例化?视图显示“保存文件”(这只是一个字符串或一个共享枚举值),控制器接收该值,并应根据该值理解要实例化的命令接口的哪个实现(这是由于elseif进程而出现问题的部分),我已设法理解它-此模式修复了问题!你在我写回复的时候发了帖子。
@Override
public void inform(String data) {
    Map<String, String> map = new HashMap<String, int>();
    map.put(C.Controller.Commands.SELECT_MODE_VERTICES, Mode.VERTICES);
    map.put(C.Controller.Commands.SELECT_MODE_LINES), Mode.LINES);
    map.put(C.Controller.Commands.SELECT_MODE_SECTORS, Mode.SECTORS);
    if (data.equals(C.SubscriptionEvents.WINDOW_CLOSED)) {
        File tempFolder = new File("temp");
        File[] files = tempFolder.listFiles();
        if (files != null) {
            for (File f : files) f.delete();
        }
    } else if (map.containsKey(data)) {
        MainModel.setCurrentMode(map.get(key));
        display.getInfoSection().repaint();
    } 
}