【问题标题】:What is the best way to store actions as data in java?在java中将动作存储为数据的最佳方法是什么?
【发布时间】:2016-05-18 20:37:54
【问题描述】:

我在一个 android 应用程序中有一个类(活动),上面有一堆示例数学问题。您可以通过按下更改问题计数器并显示新问题的按钮来移动到不同的问题。您可以通过单击“显示工作”按钮来查看如何解决问题,该按钮会在屏幕上显示大量信息。我的问题是我有一堆看起来像这样的方法:

public void showWorkButtonClicked()
{
    if (questionCounter == 1)
        showWork1();
    else if (questionCounter == 2)
        showWork2();
    else if (questionCounter == 3)
        showWork3();
    //for how ever many questions are available
}

显然,这些 if 语句是糟糕的设计。我可以将每个函数所需的数据存储在一个类中,这在这种情况下可能会起作用(但可能只会让事情变得混乱),但是如果每个 showWork 方法都足够独特以至于不切实际怎么办。我知道如果我是在 C# 中制作应用程序,我可以简单地将代表放入一个列表中,并且会有一个优雅的解决方案。如果有人有更好的解决方案(理想情况下使用更少的代码),我很想听听。

【问题讨论】:

标签: java functional-programming


【解决方案1】:

使用Map<Integer, Runnable> 存储您的操作:

private static Map<Integer, Runnable> actions = new HashMap<Integer, Runnable>() {{
    put(1, () -> showWork1());
    put(2, () -> showWork2());
    put(3, () -> showWork3());
}};

然后查找它们:

public void showWorkButtonClicked() {
    actions.getOrDefault(questionCounter, () -> {}).run();
}

在这里,如果没有对数字执行任何操作,我将使用可运行的“什么都不做”来避免 NPE。或者,您可以:

public void showWorkButtonClicked() {
    Optional.of(questionCounter)
       .map(actions::get)
       .orElseThrow(IllegalArgumentException::new)
       .run();
}

【讨论】:

  • 如果这些int 值形成一个连续范围,Runnable[] 数组也可以。使用数组的好处是你可以真正用花括号语法来初始化它,而不是使用混淆匿名内部类反模式。
  • @Holger 这不是内部类。这是一个 static 内部类 - 很大的不同,因为只有一个实例。而且它没有被混淆(很明显)或反模式(很好)。并且数组不能解决一般情况,即从任意数字映射(连续整数是边缘情况)。
  • 无论static 与否,它都是一个过时的附加类。创建一个多余的附加类只是为了保存几个字符是一种反模式。与“优先组合优于继承”的建议明显矛盾。当您仔细放置花括号以使其看起来与具有嵌套初始化程序的嵌套类不同时,它会被混淆。
  • 查看问题代码,它似乎正是关于连续整数的“边缘情况”。这就是我对名为“...Counter”的变量的期望。
  • @holger 我正在考虑未来的访问者(这是网站的前提),他们可能有类似的问题,但不是范围。此外,这是初始化不可修改集合的一种非常巧妙的方法 - 请参阅 this popular answer 的代码块 2
【解决方案2】:

您不应在代码中放入任何数据,也不应使用专用函数来显示不同的内容。如果您想根据计数器显示数据,请使用 List 或 Map 来存储它并在单个函数中读取它以进行显示。

【讨论】:

    猜你喜欢
    • 2011-05-24
    • 2019-10-21
    • 1970-01-01
    • 2014-01-23
    • 2016-08-09
    • 2019-02-24
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    相关资源
    最近更新 更多