我将用Java开发游戏,它将拥有许多听众(动作,键,鼠标等)。
我的问题是实现听众的最佳方式。
方法1:
this.addActionListener(new ActionListener() {
// Overide methods go here
});
方法2:
创建一个新类(或多个类),它将实现ActionListener并具有不同Game Componenets的方法(按钮,移动,其他任何需要ActionListener的方法)
所以,例如。如果我正在制作按钮,那么最好做
JButton button = new JButton();
button.addActionListener(new ActionListener() {
});
或
JButton button = new JButton();
button.addActionListener(new MyActionListener());
// MyActionListener
class MyActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object objectPressed = e.getSource();
if(objectPressed.equals(button) {
System.out.println("Hello World");
}
}
}
我可以从两个方面看到优势,方法1你可以直接看到该对象发生了什么,但方法2你可以看到所有组件。
那么在开发更容易维护的大规模应用程序时,将所有侦听器放在不同的类中,还是使用方法1?
答案 0 :(得分:3)
就个人而言,我更倾向于使用“if”检查的听众。它允许我独立修改它们。
我会将该代码嵌入UI中。我将它们作为单独的类编写,并使用构造函数或DI工厂将它们作为依赖项注入。
构造函数注入:
public class YourPanel extends JPanel {
private JButton button;
public YourPanel(ActionListener buttonListener) {
this.button = new JButton("Do It");
this.button.addActionListener(buttonListener);
}
}
答案 1 :(得分:2)
首先,条款。在这两种情况下,您都在定义类,但在第一种情况下,它们被称为匿名内部类。你会发现一些文件,如MyClass$1.java
。
从这个意义上讲,我的(其他可能不同的)规则将是
1)仅对未重复使用的简单操作使用匿名内部类。对于所有其他人,使用“常规”类。
2)只有在有意义的情况下才重新使用组件。如果您有两个具有截然不同含义的按钮,请不要尝试重用相同的侦听器。创建几个。例如,如果您有两个按钮(递增和递减),则可以重复使用相同的类,因为操作将非常相似。如果您有多个具有此类按钮的值,请重用在构造函数中传递要修改的对象的类。但是不要混合使用“开始回合”按钮增加值的按钮。
<强>更新强>
顺便说一下,当你说:
我可以从两个方面看到优势,方法1你可以直接看到该对象发生了什么,但方法2你可以看到所有组件。
如果您的所有类都可以更改所有其他类,那么查看所有组件但使封装逻辑方式更加困难可能看起来更有优势。 封装意味着一些额外的工作,但最终你得到的产品更加可维护,这是一件很重要的事情。
答案 2 :(得分:2)
为了再添加一个棒,我自己,我更喜欢使用AbstractActions,或者作为一个匿名的内部类,或者更常见的是作为一个独立的独立类:
JButton myExitButton = new JButton(new MyExitAction());
作为示例,作为我的MVC Swing项目的一部分的Control类将此作为其代码的一部分:
public class Control {
// these two types below are interfaces
private Model model;
private View view;
public Control(Model model, View view) {
this.model = model;
this.view = view;
addViewListeners();
}
private void addViewListeners() {
view.setGetPageAction(new GetPageAction(this, "Get Page", KeyEvent.VK_G));
view.setSetTnRendererBtnAction(new SetTnRendererBtnAction(this, "Show Images", KeyEvent.VK_S));
view.setClearThumbNailsAction(new ClearThumbNailsAction(this, "Clear ThumbNails", KeyEvent.VK_C));
view.setSetDestinationAction(new SetDestinationAction(this, "Set Destination", KeyEvent.VK_T));
view.setDownloadAction(new DownloadAction(this, "Download", KeyEvent.VK_D));
view.setExitAction(new ExitAction(this, "Exit", KeyEvent.VK_X));
model.addPropertyChangeListener(new ModelListener());
}
public View getView() {
return view;
}
public Model getModel() {
return model;
}
// .....
}
作为我所有AbstractActions基础的抽象类看起来像这样:
public abstract class MyAbstractAction extends AbstractAction {
protected Control control;
protected Model model;
protected View view;
public MyAbstractAction(Control control, String txt, int mnemonic) {
super(txt);
putValue(MNEMONIC_KEY, mnemonic);
this.control = control;
this.model = control.getModel();
this.view = control.getView();
}
}
一个警告:请注意,我不是一个专业的程序员,而是一个嗜好的人,所以虽然我的想法对我有用,但他们可能并不代表该领域的绝对最佳。所有的更正和建议都是最受欢迎的。我上面设计的一个弱点是,我认为我是以笨拙的方式“注入”我的动作。
答案 3 :(得分:0)
老实说,我更喜欢第一个。你是对的第一种方法,你可以很容易地看到该组件正在发生什么。然而。有时按钮可能会有相同的行为或相同的ActionListener,据说我更喜欢方法2.所以你可以轻松地重用actionListeners。
答案 4 :(得分:0)
您还可以看看我一直在研究的名为swingobjects的摇摆框架。
https://github.com/Sethuraman/swingobjects
如果使用FrameFactory类创建Jframe,swingobjects将为您在框架中声明的所有小部件注册GlobalListener。这允许您做的是,使用如下注释标记框架中的方法:
@Action("<action name or button text>")
public void performAction(ActionEvent evt){
....
}
GlobalListener将通过反射调用此方法。这意味着,您不必编写if块,创建匿名内部类。一切都是透明处理的。看看框架......