java - 两个重载的方法,相同的 Action ,导致重复代码

标签 java javafx javafx-8

我有两种方法采用CircleScene 并通过更改fill 使背景闪烁红-绿-蓝每 N 毫秒计算一次值。

两种方法:

private void makeRGB(Circle c) {
    Timer t = new Timer();
    t.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            if(c.getFill() == Color.RED) {
                c.setFill(Color.GREEN);
            } else if (c.getFill() == Color.GREEN) {
                c.setFill(Color.BLUE);
            } else {
                c.setFill(Color.RED);
            }
        }
    },0, RGB_CHANGE_PERIOD);
}

private void makeRGB(Scene s) {
    Timer t = new Timer();
    t.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            if(s.getFill() == Color.RED) {
                s.setFill(Color.GREEN);
            } else if (s.getFill() == Color.GREEN) {
                s.setFill(Color.BLUE);
            } else {
                s.setFill(Color.RED);
            }
        }
    },0, RGB_CHANGE_PERIOD);
}

显然它们非常相似,但是由于 CircleScene 不在同一个继承树中,我不能使用调用它们的父类(super class)的方法包含 .setFill()/.getFill() 方法。

我将如何去除此处的代码重复?

最佳答案

通常,您可以通过将通用代码分解为函数/方法/类并对不同部分进行参数化来删除重复代码。在这种情况下,不同的是您检索当前填充的方式,以及您设置新填充的方式。 java.util.function package 提供了适当的类型来参数化这些,所以你可以这样做:

private void makeRGB(Circle c) {
    makeRGB(c::getFill, c:setFill);
}

private void makeRGB(Scene s) {
    makeRGB(s::getFill, s:setFill);
}

private void makeRGB(Supplier<Paint> currentFill, Consumer<Paint> updater) {
    Timer t = new Timer();
    t.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            if(currentFill.get() == Color.RED) {
                updater.accept(Color.GREEN);
            } else if (currentFill.get() == Color.GREEN) {
                updater.accept(Color.BLUE);
            } else {
                updater.accept(Color.RED);
            }
        }
    },0, RGB_CHANGE_PERIOD);
}

但请注意,您不应从后台线程更改 UI。你真的应该这样做

private void makeRGB(Supplier<Paint> currentFill, Consumer<Paint> updater) {
    Timer t = new Timer();
    t.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            Platform.runLater(() -> {
                if(currentFill.get() == Color.RED) {
                    updater.accept(Color.GREEN);
                } else if (currentFill.get() == Color.GREEN) {
                    updater.accept(Color.BLUE);
                } else {
                    updater.accept(Color.RED);
                }
            }
        }
    },0, RGB_CHANGE_PERIOD);
}

或者,(更好),use a Timeline定期做事。

如评论中所述,您还可以提供一个 Map,将每种颜色映射到它之后的颜色。结合所有这些给出:

private final Map<Paint, Paint> fills = new HashMap<>();

// ...

    fills.put(Color.RED, Color.GREEN);
    fills.put(Color.GREEN, Color.BLUE);
    fills.put(Color.BLUE, Color.RED);

// ...

private void makeRGB(Circle c) {
    makeRGB(c::getFill, c:setFill);
}

private void makeRGB(Scene s) {
    makeRGB(s::getFill, s:setFill);
}

private void makeRGB(Supplier<Paint> currentFill, Consumer<Paint> updater) {

    Timeline timeline = new Timeline(Duration.millis(RGB_CHANGE_PERIOD), 
        e-> updater.accept(fills.get(currentFill.get())));
    timeline.setCycleCount(Animation.INDEFINITE);
    timeline.play();
}

关于java - 两个重载的方法,相同的 Action ,导致重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47931571/

相关文章:

java - observablelist 更改后,JavaFX 8 ListView 仍然显示旧列表的一部分

java - Android,关于服务绑定(bind)的快速问题

java - Jline 终端编写器输出格式错误的输出

JavaFx 在表列上使用 String 和 Double

java - 使用 fxml 将事件监听器添加到 Javafx 中的 mainScene

java - 有什么方便的方法可以将 w3c Document 转换为 jsoup one

网格 Pane 上的 JavaFX 拖放事件

java - 尝试登录会生成 java.lang.NoClassDefFoundError 和 java.lang.ClassNotFoundException 错误

java - 从字符串中提取目录

java - 在 Pane 或区域内使用备用坐标系