如何在Java中设计ActionListener类?
注意:我正在学习干净的代码、设计模式和面向对象编程,所以回答时请记住这一点 我有一个窗口,上面有一堆如何在Java中设计ActionListener类?,java,swing,actionlistener,Java,Swing,Actionlistener,注意:我正在学习干净的代码、设计模式和面向对象编程,所以回答时请记住这一点 我有一个窗口,上面有一堆JButtons和一个TextField。下面是单独文件中的Window类: // Window.java public class Window { JTextField textField; JButton button1; JButton button2; ... } 以下是我想要的: 当我按下button1时,我希望textField显示“1”,当我按下b
JButtons
和一个TextField
。下面是单独文件中的Window类:
// Window.java
public class Window {
JTextField textField;
JButton button1;
JButton button2;
...
}
以下是我想要的:
当我按下button1
时,我希望textField
显示“1”,当我按下button2
显示“2”时,等等。下面是一个单独的文件中的ActionListener类,这是我希望它执行的操作:
//TextInputActionListener.java
public class TextInputActionListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1) {
textField.setText("1");
}
else if (e.getSource() == button 2) {
textField.setText("2");
}
}
}
很明显,这是行不通的,所以我的问题是我应该如何定义这个类?
- 我应该将其声明为
窗口的内部类吗?
- 我应该为它创建一个单独的类吗?(我可以让
窗口
类实现
,这样就可以解决问题了)ActionListener
注意:正如您所看到的,问题不在于如何做,而在于如何以支持面向对象设计的方式来做。在您当前的结构中,
窗口
类可以实现ActionListener
,因为它负责监听视图中的事件。内部类也可以接受,但可能会导致代码更加混乱。你应该警惕过度的关注点分离。您应该只在模型、视图和控制器方面真正地分离代码
一定要检查一下设计模式。根据您当前的结构,
窗口
类可以实现ActionListener
,因为它负责监听视图中的事件。内部类也可以接受,但可能会导致代码更加混乱。你应该警惕过度的关注点分离。您应该只在模型、视图和控制器方面真正地分离代码
一定要查看设计模式。因为监听器类通常需要访问GUI类的字段(如您的
窗口
),所以使用监听器的内部类是一个好主意
当然,并不禁止Window
实现ActionListener
,但随后您将在公共API中公开实现细节,您应该考虑是否需要这样做
请注意,Java 8的lambdas和方法句柄为您提供了编写侦听器代码的更多可能性:
class Window {
JTextField textField;
JButton button1;
JButton button2;
Window()
{
button1.addActionListener(event -> textField.setText("1"));
...
}
}
由于监听器类通常需要访问GUI类的字段(如
窗口
),因此使用监听器的内部类是一个好主意
当然,并不禁止Window
实现ActionListener
,但随后您将在公共API中公开实现细节,您应该考虑是否需要这样做
请注意,Java 8的lambdas和方法句柄为您提供了编写侦听器代码的更多可能性:
class Window {
JTextField textField;
JButton button1;
JButton button2;
Window()
{
button1.addActionListener(event -> textField.setText("1"));
...
}
}
以下是我对这个问题的看法:
- 是否应将
实现声明为窗口的内部类我不会的。这是因为当存在与包含类的状态密切相关的功能时,会使用内部类。例如,ActionListener
实现可以编写为迭代器
实现的内部类。在这种情况下,集合
实现可以访问迭代器
实现的私有数据成员。另一个例子是.internal类可以访问父类的私有成员,因此应该谨慎使用集合
- 您是否应该为它创建一个单独的类?是的,您应该在一个单独的文件中以最低的访问级别声明它。您不想让
类实现窗口
——仅仅因为这会让窗口类负责处理它包含的所有控件的事件——违反关注点分离(单一责任原则)。因此,想象一下您将要编写的代码-它将充满一长串ActionListener
条件或一个用于识别事件源的切换案例。这显然意味着,如果向窗口类添加新控件,则会增加if
或if
块的长度。在一个单独的类中声明action listener允许分离关注点,也有助于可测试性switch
希望这有帮助以下是我对这个问题的看法:
- 是否应将
实现声明为窗口的内部类我不会的。这是因为当存在与包含类的状态密切相关的功能时,会使用内部类。例如,ActionListener
实现可以编写为迭代器
实现的内部类。在这种情况下,集合
实现可以访问迭代器
实现的私有数据成员。另一个例子是.internal类可以访问父类的私有成员,因此应该谨慎使用集合
- 您是否应该为它创建一个单独的类?是的,您应该在一个单独的文件中以最低的访问级别声明它。您不想让
类实现窗口
——仅仅因为这会让窗口类负责处理它包含的所有控件的事件——违反关注点分离(单一责任原则)。因此,想象一下您将要编写的代码-它将充满一长串ActionListener
条件或一个用于识别事件源的切换案例。这显然意味着,如果向窗口类添加一个新控件,那么if
// TextInputListener.java public class TextInputListener implements ActionListener { Window window; @Override public void actionPerformed(ActionEvent e) { if (window.isButton0(e)) { //textField.setText("0") } else if (window.isButton1(e)) { //textField.setText("1") } ... } }
// Window.java public class Window { TextField textField; JButton button1; JButton button2; ... void setText(String text) { textField.setText(text); } } // TextInputListener.java public class TextInputListener implements ActionListener { Window window; @Override public void actionPerformed(ActionEvent e) { if (window.isButton0(e)) { window.setText("0"); } else if (window.isButton1(e)) { window.setText("1"); } ... } }
public void listenTo(Window window) { this.window = window; }
public void setActionListener(ActionListener l) { for (int i = 0; i < buttons.length; i++) { buttons[i].addActionListener(l); } }
// MyApp.java public class MyApp { public static void main(String[] args) { Window myWindow = new Window(); TextInputListener myTextInputListener = new TextInputListener(); myWindow.setActionListener(myTextInputListener); myTextInputListener.listenTo(myWindow); } } // Window.java public class Window { TextField textField; JButton button1; JButton button2; ... void setText(String text) { textField.setText(text); } public void setActionListener(ActionListener l) { for (int i = 0; i < buttons.length; i++) { buttons[i].addActionListener(l); } } } // TextInputListener.java public class TextInputListener implements ActionListener { Window window; public void listenTo(Window window) { this.window = window; } @Override public void actionPerformed(ActionEvent e) { if (window.isButton0(e)) { window.setText("0"); } else if (window.isButton1(e)) { window.setText("1"); } ... } }