使用命令模式,告别if-else
2012-04-21 19:58 java线程例子 阅读(582) 评论(0) 编辑 收藏 举报
直接看下面的例子:下面一个按钮当做一个命令
若使用命令模式编写:
可以看到第二类不再需要if-else,若此时分别向两个类添加多一个按钮(一个命令),前面的类需要向actionPerformed添加多一个if-else,而后一个类则不需要。因此使用命令模式能简化程序的控制,同时,也能很容易的添加新的命令类。另外,命令模式还有其他的好处,如提高松耦合,降低类与类之间的依赖性等等。(把上面例子中的内部类分别独立开来,就能体现松耦合。)
最后附上Java高级编程中的另一个例子:
package command; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class ButtonPanel extends JPanel implements ActionListener{ private static final long serialVersionUID = 4715122374780095560L; private JButton bt1, bt2, bt3; public ButtonPanel(){ bt1 = new JButton1("按钮1"); bt1.addActionListener(this); bt2 = new JButton2("按钮2"); bt2.addActionListener(this); bt3 = new JButton3("按钮3"); bt3.addActionListener(this); add(bt1); add(bt2); add(bt3); } public void actionPerformed(ActionEvent e) { JButton bt = (JButton)e.getSource(); if(bt == bt1){ System.out.println("你点击了"+bt.getText()); }else if(bt == bt2){ System.out.println("你点击了"+bt.getText()); }else{ System.out.println("你点击了"+bt.getText()); } } //一个按钮--->一个命令 private class JButton1 extends JButton{ public JButton1(String text){ super(text); } } private class JButton2 extends JButton{ public JButton2(String text){ super(text); } } private class JButton3 extends JButton{ public JButton3(String text){ super(text); } } public static void main(String[] args){ JFrame frame = new JFrame(); frame.add(new ButtonPanel()); frame.setSize(300,100); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
若使用命令模式编写:
package command; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class ButtonPanel1 extends JPanel implements ActionListener{ private static final long serialVersionUID = 4715122374780095560L; private JButton bt1, bt2, bt3; public interface Command{ public void excute(); } public ButtonPanel1(){ bt1 = new JButton1("按钮1"); bt1.addActionListener(this); bt2 = new JButton2("按钮2"); bt2.addActionListener(this); bt3 = new JButton3("按钮3"); bt3.addActionListener(this); add(bt1); add(bt2); add(bt3); } public void actionPerformed(ActionEvent e) { Command command = (Command)e.getSource(); command.excute(); } private class JButton1 extends JButton implements Command{ private String text; public JButton1(String text){ super(text); this.text = text; } public void excute() { System.out.println("你点击了"+text); } } private class JButton2 extends JButton implements Command{ private String text; public JButton2(String text){ super(text); this.text = text; } public void excute() { System.out.println("你点击了"+text); } } private class JButton3 extends JButton implements Command{ private String text; public JButton3(String text){ super(text); this.text = text; } public void excute() { System.out.println("你点击了"+text); } } public static void main(String[] args){ JFrame frame = new JFrame(); frame.add(new ButtonPanel1()); frame.setSize(300,100); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
可以看到第二类不再需要if-else,若此时分别向两个类添加多一个按钮(一个命令),前面的类需要向actionPerformed添加多一个if-else,而后一个类则不需要。因此使用命令模式能简化程序的控制,同时,也能很容易的添加新的命令类。另外,命令模式还有其他的好处,如提高松耦合,降低类与类之间的依赖性等等。(把上面例子中的内部类分别独立开来,就能体现松耦合。)
最后附上Java高级编程中的另一个例子:
package layout; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Hashtable; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JRadioButton; //实现命令模式接口后,应用程序就可以根据用户导航操作在运行时通过多种形式派生出合适的事件动作 public class BorderLayoutPanel extends JPanel implements ActionListener { private static final long serialVersionUID = 6332313305423197159L; private final static String buttonText = "<html><center><font size = '+2'>基本算术</font>" + "<br/><br/>点击获取问题</center></html>"; private static String[] questions = { "1, 2, 1 + 1 = ?, 0, 1, 2, 3", "2, 0, 1 - 1 = ?, 0, 1, 2, 3", "3, 2, 5 - 3 = ?, 0, 1, 2, 3", "4, 3, 4 - 1 = ?, 0, 1, 2, 3" }; private Hashtable<String, String[]> hashtableQuestions = new Hashtable<String, String[]>(); private JPanel answerPanel, northPanel, centerPanel, eastPanel; private ButtonGroup optionGroup;//按钮组 private JLabel msgText;//提示消息 private JButton resetButton, infoScreenButton;// 重新开始 private JRadioButton blankRadioButton;//blankRadioButton用来清空选项 private JRadioButton[] answer;// 放置选项的单选按钮 private JQuestionButton centerButton;//中间的那个按钮 private JProgressBar progressBar;//进度天 private int numberQuestionAnswered;// 已经回答的问题数 private int correctAnswerCount;// 回答正确的个数 private int numberQuestions = 0;// 问题个数 private int questionCount = 1;// 第几个问题 private int numberAnswers;// 选项个数 private String[] question = null;//类似"1, 2, 1 + 1 = ?, 0, 1, 2, 3"的一个字符串组 private boolean questionAnswered = true;;//是否已经回答过该问题 //想想如果没有这个Command接口,在actionPerformed方法里就得有使用几个if进行判断 public interface Command { public void excute(); } public BorderLayoutPanel() { initComponents(); } public void initComponents() { removeAll(); northPanel = new JPanel(); answerPanel = new JPanel(); centerPanel = new JPanel(); eastPanel = new JPanel(); //初始化数据 numberQuestionAnswered = 0; correctAnswerCount = 0; questionCount = 1; msgText = new JLabel("点击按钮开始!"); infoScreenButton = new RulesButton("规则"); infoScreenButton.addActionListener(this); optionGroup = new ButtonGroup(); progressBar = new JProgressBar(); String[] strLine = null; for (int x = 0; x < questions.length; ++x) { strLine = questions[x].split(","); hashtableQuestions.put(strLine[0], strLine); } centerButton = new JQuestionButton(); centerButton.setText(buttonText); centerPanel.add(centerButton); centerButton.addActionListener(this); centerPanel.setLayout(new GridLayout(0, 1)); answerPanel.setLayout(new GridLayout(0, 1)); String a[] = hashtableQuestions.get(String.valueOf(questionCount)); System.out.println(a.length); numberAnswers = a.length - 3; answer = new JRadioButtonAnswer[numberAnswers];// 可供选择的答案 for (int i = 0; i < numberAnswers; ++i) { answer[i] = new JRadioButtonAnswer(a[i + 3]); answerPanel.add(answer[i]); answer[i].addActionListener(this); optionGroup.add(answer[i]); } blankRadioButton = new JRadioButton(); optionGroup.add(blankRadioButton); northPanel.setBackground(new Color(255, 255, 220)); northPanel.add(msgText); eastPanel.setLayout(new GridLayout(0, 1)); eastPanel.add(progressBar); eastPanel.add(answerPanel); eastPanel.add(infoScreenButton); setLayout(new BorderLayout()); add(northPanel, BorderLayout.NORTH); add(eastPanel, BorderLayout.EAST); add(centerPanel, BorderLayout.CENTER); questionAnswered = true; answerPanel.setVisible(false); numberQuestions = questions.length; progressBar.setMaximum(numberQuestions); progressBar.setValue(0); // 设置进度条的 indeterminate // 属性,该属性确定进度条处于确定模式中还是处于不确定模式中。不确定进度条连续地显示动画,指示发生未知长度的操作。 progressBar.setIndeterminate(false); resetButton = new JRestButton("重新开始!"); resetButton.addActionListener(this); } //actionPerformed方法中只含俩句语句,正式Command接口带来的便利,也是命令模式带来的便利 public void actionPerformed(ActionEvent e) { Command obj = (Command) e.getSource(); obj.excute(); } //JQuestionButton实现了Command接口 private class JQuestionButton extends JButton implements Command { private static final long serialVersionUID = -8614071548129227665L; public JQuestionButton() { super(); } public void excute() { if (numberQuestionAnswered < numberQuestions) { answerPanel.setVisible(true); northPanel.setBackground(new Color(255, 255, 220)); if (questionAnswered) { optionGroup.setSelected(blankRadioButton.getModel(), true); questionAnswered = false; String key = Integer.toString(questionCount); if (hashtableQuestions.containsKey(key)) { question = (String[]) hashtableQuestions.get(key); questionCount++; } else { System.out.println("找不到指定键" + key); } } msgText.setText(question[2]); for (int i = 0, x = 3; i < numberAnswers; i++) { answer[i].setText(question[x + i]); } } } } //JRadioButtonAnswer实现了Command接口 private class JRadioButtonAnswer extends JRadioButton implements Command { private static final long serialVersionUID = 7112470314050331612L; public JRadioButtonAnswer(String caption) { super(caption); } public void excute() { if (!questionAnswered) { if (question[1].trim().equals(getText().trim())) { msgText.setText("正确!"); northPanel.setBackground(Color.green); correctAnswerCount++; } else { msgText.setText("错误!答案是:" + question[1]); northPanel.setBackground(Color.red); } questionAnswered = true; numberQuestionAnswered++; centerButton.setText("<html><center><font size = '+2'>点击获取问题 </font><br/><br/>" + " Score = " + correctAnswerCount + "/" + numberQuestionAnswered + "</center></html>"); progressBar.setValue(numberQuestionAnswered); progressBar.setStringPainted(true); // Math.round返回最接近参数的 long。 progressBar.setString(Double.toString(Math.round(progressBar .getPercentComplete() * 100)) + "%"); if (numberQuestionAnswered >= numberQuestions) { centerButton.setBackground(new Color(255, 255, 220)); centerButton.setText("完成测试! 分数 = " + String.valueOf((float) correctAnswerCount / (float) numberQuestionAnswered * 100) + "%"); answerPanel.removeAll(); answerPanel.add(resetButton); } } else { msgText.setText("你已经回答了这个问,请选择下一个问题!"); } } } //RulesButton实现了Command接口 private class RulesButton extends JButton implements Command { private static final long serialVersionUID = 7258272633949950344L; public RulesButton(String title) { super(title); } public void excute() { JLabel infoLable = new JLabel( "<html><font size='+2'><center>游戏说明:点击按钮来产生问题。</font></center></html>"); JFrame infoFrame = new JFrame("游戏规则"); infoFrame.add(infoLable); infoFrame.setSize(400, 150); infoFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); infoFrame.setVisible(true); } } //JRestButton实现了Command接口 private class JRestButton extends JButton implements Command { private static final long serialVersionUID = 3588747199875249280L; public JRestButton(String caption) { super(caption); } public void excute() { initComponents(); } } public static void main(String[] args) { JFrame frame = new JFrame(); frame.add(new BorderLayoutPanel()); frame.setSize(600, 600); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }