【问题标题】:How can I generalize these repetitive blocks of code?如何概括这些重复的代码块?
【发布时间】:2014-07-20 17:40:28
【问题描述】:

像这样带有几乎相同块的代码让我畏缩。再加上它加起来你有一千行代码,其中一半就足够了。当然有一种方法可以创建一个循环来实现这一切,并且不会有看起来如此简单和无脑的代码。

这样做似乎会添加尽可能多的代码,因为我试图减少:循环制作 5 个按钮,按钮的标签数组,背景数组......也许更多。即使事实证明这是可以接受的,我将如何制作一个循环来处理听众? 我不能有一组方法,可以吗?我猜这样的循环必须包含switch。是的?如果我不想寻求更好的解决方案,我可能会这样做。所以我问...

什么样的代码会监听整个按钮组并根据被按下的按钮采取行动?我会将单个侦听器分配给哪个组件?以及如何?

(如果我意识到我已经知道如何做到这一点并且甚至不需要一开始就问,那么这个问题的答案可能会让我更加畏缩,而不是代码的重复性,但无论如何我还是要问。我正处于大脑想要退出的那些我今天已经拥有的点之一。)

  private void makeScoremasterBonuses(){
    pnlBonuses = new JPanel(new GridLayout(1, 6));
    pnlBonuses.setSize(6,1);

    JButton t1 = (new JButton("3W"));
    t1.setToolTipText("This is a triple-word cell.");
    t1.setBackground(TRIPLE_WORD);
    t1.setHorizontalAlignment(JButton.CENTER);
    t1.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        Highlighter.shadeSymmetric(currentCell,TRIPLE_WORD);
      }});

    JButton t2 = (new JButton("3L"));
    t2.setToolTipText("This is a triple-letter cell");
    t2.setBackground(TRIPLE_LETTER);
    t2.setHorizontalAlignment(JButton.CENTER);
    t2.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        Highlighter.shadeSymmetric(currentCell,TRIPLE_LETTER);
      }});

    JButton t3 = (new JButton("2W"));
    t3.setToolTipText("This is a double-word cell");
    t3.setBackground(DOUBLE_WORD);
    t3.setHorizontalAlignment(JButton.CENTER);
    t3.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        Highlighter.shadeSymmetric(currentCell,DOUBLE_WORD);
      }});

    JButton t4 = (new JButton("2L"));
    t4.setToolTipText("This is a double-letter cell");
    t4.setBackground(DOUBLE_LETTER);
    t4.setHorizontalAlignment(JButton.CENTER);
    t4.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        Highlighter.shadeSymmetric(currentCell,DOUBLE_LETTER);
      }});

    JButton t5 = (new JButton(""));
    t5.setToolTipText("No bonus");
    t5.setBackground(WHITE);
    t5.setHorizontalAlignment(JButton.CENTER);
    t5.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        Highlighter.shadeSymmetric(currentCell,B_NORMAL);
      }});

    pnlBonuses.add(new JLabel("Legend: "));
    pnlBonuses.add(t1);    
    pnlBonuses.add(t2);     
    pnlBonuses.add(t3);     
    pnlBonuses.add(t4);     
    pnlBonuses.add(t5);

  }

我不是要求任何人编写代码;我什至不想那样(但我不能忽视它!)。

以上代码的作用如下:

【问题讨论】:

  • JButton 是否在任何类型的控件集合中?我们在谈论多少个按钮?如果不超过四个,那就不值得尝试合并代码了。
  • @Robert--你所看到的就是我所拥有的。不过,我真的不知道该怎么回答你。所以我猜是“不”。我想我应该谷歌“控件集合”并从那里开始学习。我已经开始制作一系列按钮、标签和背景,但仍然有关于一个听众的问题。感谢您的回复。
  • @DSlomer64 看看 Qwerky 对这个问题的回答:stackoverflow.com/questions/5936261/…
  • @Alan--我想你已经预料到我的“另一个线程”在我对我的问题的“回答”结束时的沉思(下)!这是另一个我以前没有去过的地方--setActionCommand,非常感谢!这是一个很好的提示!
  • 我会收回这一点——我以前用过setActionCommand,只是没有在适当的上下文中使用——作为一种无知的解决方法:here

标签: java jcomponent generalization


【解决方案1】:

识别变化的方面,收集它们,并迭代收集。

类似这样的东西(未经测试):

pnlBonuses = new JPanel(new GridLayout(1, 6));
pnlBonuses.setSize(6,1);
pnlBonuses.add(new JLabel("Legend: "));

// Create class "CellInfo" with constructor and getters for desired properties.
CellInfo cellInfos[] = {
  new CellInfo("3W", "This is a triple-word cell.",   TRIPLE_WORD),
  new CellInfo("3L", "This is a triple-letter cell.", TRIPLE_LETTER),
  // ...
};

// Add a button for each item described by the cellInfos.
for (CellInfo cellInfo : cellInfos) {
  Button b = new JButton(cellInfo.getLabel());
  b.setToolTipText(cellInfo.getToolTipText());
  b.setBackground(cellInfo.getBackground());
  b.setHorizontalAlignment(JButton.CENTER);
  b.addActionListener(new ActionListener() {
  @Override public void actionPerformed(ActionEvent e) {
    Highlighter.shadeSymmetric(currentCell, cellInfo.getBackground());
  }});
  pnlBonuses.add(b);
}

请注意,您可能需要为占位符创建一些“最终”变量,以便在内部匿名类中使用,但这个想法应该可行。

【讨论】:

  • @maerics--我喜欢我所看到的!我将致力于实现类似的东西。谢谢! (我更喜欢使用 EDIT!)[事后思考:我不在乎按下哪个按钮,只要它做我想要的,所以没有按钮阵列是必要的,不像我假设的那样。]
【解决方案2】:

通常,每当您重复使用类似的功能时,您都希望将该代码提取到一个辅助方法中,如下所示:

private JButton makeJButton(String label, String toolTip, Color bgColor, final Color highlight) {
    JButton button = new JButton(label);
    button.setToolTipText(toolTip);
    button.setBackground(bgColor);
    button.setHorizontalAlignment(JButton.CENTER);
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            Highlighter.shadeSymmetric(currentCell, highlight);
        }
    });
    return button;
}

那么你的makeScoremasterBonuses() 方法就变得简单多了:

private void makeScoremasterBonuses() {
    pnlBonuses = new JPanel(new GridLayout(1, 6));
    pnlBonuses.setSize(6, 1);

    pnlBonuses.add(new JLabel("Legend: "));
    pnlBonuses.add(makeJButton("3W", "This is a triple-word cell.", TRIPLE_WORD, TRIPLE_WORD));
    pnlBonuses.add(makeJButton("3L", "This is a triple-letter cell.", TRIPLE_LETTER, TRIPLE_LETTER));
    pnlBonuses.add(makeJButton("2W", "This is a double-word cell.", DOUBLE_WORD, DOUBLE_WORD));
    pnlBonuses.add(makeJButton("3L", "This is a double-letter cell.", DOUBLE_LETTER, DOUBLE_LETTER));
    pnlBonuses.add(makeJButton("", "No bonus.", WHITE, B_NORMAL));
}

【讨论】:

  • +1 我比我自己的答案更喜欢这个,因为你不需要中级课程。
  • @azure——我也喜欢这个。谢谢。现在我有三个答案来选择“最好的”。会很艰难我特别喜欢你答案中的“一般......”部分作为一个很好的解释。 Maerics的一句话解释,也很好。这些是我们在这里需要更多的答案,恕我直言。至少他们为我工作。
【解决方案3】:

enum 可能是您的朋友。这几乎是一个方法数组

static enum Btn {

    TripleWord("3W", "This is a triple word cell.", TRIPLE_WORD),
    TripleLetter("3L", "This is a triple letter cell.", TRIPLE_LETTER),
    DoubleWord("2W", "This is a double word cell.", DOUBLE_WORD),
    DoubleLetter("2L", "This is a double letter cell.", DOUBLE_LETTER),
    NoBonus("", "No bonus.", WHITE, B_NORMAL);
    final String label;
    final String tooltip;
    final Color color;
    final Color shade;

    Btn(String label, String tooltip, Color color, Color shade) {
        this.label = label;
        this.tooltip = tooltip;
        this.color = color;
        this.shade = shade;
    }

    Btn(String label, String tooltip, Color color) {
        this(label, tooltip, color, color);
    }

    public JButton asJButton() {
        JButton btn = (new JButton(label));
        btn.setToolTipText(tooltip);
        btn.setBackground(color);
        btn.setHorizontalAlignment(JButton.CENTER);
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Highlighter.shadeSymmetric(currentCell, shade);
            }
        });
        return btn;
    }
}

private void makeScoremasterBonuses() {
    int nBtns = Btn.values().length;
    JPanel pnlBonuses = new JPanel(new GridLayout(1, nBtns + 1));
    pnlBonuses.setSize(nBtns + 1, 1);
    pnlBonuses.add(new JLabel("Legend: "));
    for (Btn btn : Btn.values()) {
        pnlBonuses.add(btn.asJButton());
    }
}

【讨论】:

  • @OldC--谢谢!我一直想掌握enum--非常肤浅地使用了一两次。事实上,我希望使用它来避免两次“三字”的东西,因为我记得你可以打印枚举值,但我太容易放弃了。我会研究你和所有其他的答案。我希望我可以选择多个作为“答案”,但至少我已经全部投了赞成票。
  • @OldCurmudgeon--您的回答使我的enum 水平比我用过的要高得多--这充其量只是表面上的。随着(在我看来)所有的钟声等等。我不知道我是否应该将我所看到的称为“枚举构造函数”,但那是我没有去过的地方,所以感谢您打开门。
  • @DSlomer64 - 请注意,我们可以使用列表中的枚举数来控制GridLayout 的大小和面板大小。
  • @OldCurmudgeon--我将很快提出一个相关问题(在另一个线程中),这将是关于 enumvalues() 以及如何(如果可能)将这些值用作文本.但是我想先玩一下枚举,因为我还没有完全弄清楚你的代码是如何工作的,所以我可能会用它作为我的探索点。
【解决方案4】:

=== 这是对我一小时前发布的内容的重大修改 ===

我想看看我是否可以实现自己的幼稚方法。这里是:

public class Game implements ActionListener{

  public Color [] backgrounds = {TRIPLE_WORD, TRIPLE_LETTER, 
                                 DOUBLE_WORD, DOUBLE_LETTER, B_NORMAL};

  private void makeScoremasterBonuses(){
    String[] labels = {"3W", "3L", "2W", "2L", "  "};
    JButton but;

    pnlBonuses = new JPanel();
    pnlBonuses.add(new JLabel("Legend:"));

    for (int i = 0; i < labels.length; i++) {
      char wt = labels[i].charAt(0);
      char tp = labels[i].charAt(1);
      but = new JButton(labels[i]);//("" + i);
      but.setBackground(backgrounds[i]);
      but.setHorizontalAlignment(SwingConstants.CENTER);
      but.setActionCommand("" + i);
      but.addActionListener(this);
      but.setToolTipText("This is a " 
          + (i == labels.length - 1 ? "non-bonus" :
                          (wt == '3' ? "triple" : "double") 
                  + " " + (tp == 'L' ? "letter" : "word")) 
          + " cell.");
      pnlBonuses.add(but);
    }    
  }

  public void actionPerformed(ActionEvent evt) {
    int i = Integer.parseInt(evt.getActionCommand());
    Highlighter.shadeSymmetric(currentCell,backgrounds[i]);
  }

现在(在编辑后)这是我发起的最好的线程,就响应的质量和我从中学到的一切而言。谢谢大家。

但我仍然没有设法适当地使用setActionCommand。无论我为尝试使用它所做的一切,最终都会在代码方面变得更长,以至于我放弃了并选择了简短而简单但不合适的方法。

关于如何正确使用set...getActionCommand 有任何想法(即,作为操作)无需添加大量代码吗?

【讨论】:

  • 在每个人的回答中看到 ("3W", "This is a triple word cell.", TRIPLE_WORD) 之类的东西让我想到...“你知道,这 3 条信息可能来自一个 ——enum:private enum Actions { TRIPLE_WORD, TRIPLE_LETTER, DOUBLE_WORD, DOUBLE_LETTER, NOT_A_BONUS } 。我不知道是开始另一个线程还是编辑我自己的答案并在那里提出问题。我想我会等到有人建议。
  • 是的,我是!当然!关于我要去哪里!
【解决方案5】:

(我知道我可以编辑我之前的答案,但这个答案太不一样了......)

感谢@OldCurmudgeon,我想出了我认为非常好的方法。

这是“证明”(我可能会保留每个标签和工具提示):

  public enum Colors {
    TRIPLE_WORD    (255, 220,  50), 
    TRIPLE_LETTER  (255, 255, 150), 
    DOUBLE_WORD    (  0, 255,   0), 
    DOUBLE_LETTER  (214, 245, 214),
    NOT_A_BONUS    (255, 255, 255);

    private final int red, green, blue;

    Colors(int r, int g, int b){
      this.red   = r;
      this.green = g;
      this.blue  = b;
     }

    public java.awt.Color background(Colors c){
      return new java.awt.Color(c.red, c.green, c.blue);
    }
  }

  private void makeScoremasterBonuses(){
    Colors c;
    Colors all   [] = Colors.values();
    String labels[] = new String[all.length];
    String abbrs [] = new String[all.length];

    JButton but;
    pnlBonuses = new JPanel();
    pnlBonuses.add(new JLabel("Legend:"));

    for (int i = 0; i < all.length; i++) {
      labels[i] = all[i].name().replace("_", " ").toLowerCase();
      abbrs [i] = abbreviate(all[i].name());
      c = Colors.values()[i];
      but = new JButton(abbrs[i]);
      but.setToolTipText(labels[i]);
      but.setBackground(c.background(c));
      but.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
      but.setActionCommand("" + i);
      but.addActionListener(this);
      pnlBonuses.add(but);
    }
  }

【讨论】:

  • 谢谢你,@OldCurmudgeon,让我开始使用上面的代码!我所做的只是谷歌“Java 中的枚举构造函数”,它把我带到了this link,它仅仅通过模仿我在那里看到的以及你的代码,引导我到一个全新的地方。多么美好的一天!
  • 我真的很喜欢你在发展你的知识的同时,在改进你的解决方案(正如你最初要求的那样)以及在此过程中与其他人的整体互动方面的热情。我认为这是一个最好的例子,说明问答对话如何教导和启发我们,而不是仅仅接受简单的答案(尤其是在阅读了一系列因各种原因关闭问题之后,恕我直言,比许多关闭者花时间考虑的更相关)。
  • @Zhora--多么好的评论,尤其是关于封闭式问题。在 SO 和你的帖子中似乎有很多脾气暴躁(急躁?)——尤其是在这个帖子结束几个月后——这表明周围也有足够的积极性。谢谢。
猜你喜欢
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 2018-08-23
  • 1970-01-01
  • 2023-03-31
  • 2020-11-06
  • 2016-09-03
  • 1970-01-01
相关资源
最近更新 更多