使用单例监听器统一处理Swing组件命令模式实战

本文详细介绍了如何在Java Swing应用中通过单例监听器统一处理JMenuItem和JButton等组件的动作事件,实现命令模式与界面组件的优雅结合,减少重复监听器代码。

Command, Singleton, JMenuItem, JButton, AbstractButton - 为应用实现单一监听器

这里我将演示如何为整个系统使用单一监听器来处理JMenuItem的简单用法。一个典型的使用场景可能是单实例桌面应用程序。

让我们看看具体实现方式。首先创建一个OneListener类,它需要能够监听ActionEvents并能向自身添加Commands。如果您想了解更多关于这种模式及其用法的信息,请参考我之前关于Command和Singleton的帖子。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.shaafshah.jmenus;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.AbstractButton;

// 实现ActionListener接口且为单例
public class OneListener implements ActionListener{

    private static OneListener oneListener = null;

    // 保存注册到此监听器的所有命令列表
    private ArrayList<Command> commandList = null;

    // 私有构造函数
    private OneListener(){
        commandList = new ArrayList<Command>();
    }

    // 确保单例实例
    public static OneListener getInstance(){
        if(oneListener != null)
            return oneListener;
        else return oneListener = new OneListener();
    }

    // 添加命令并将自己添加为监听器
    public void addCommand(Command command){
        commandList.add(command);
        ((AbstractButton)command).addActionListener(this);
    }

    // 所有事件都在这里处理
    @Override
    public void actionPerformed(ActionEvent e) {
        ((Command)e.getSource()).execute();
    }
}

在上面的代码中,addCommand方法添加命令对象并为其添加监听器。

这是如何实现的呢?基本上是因为我将UI对象在系统中归类为Commands,并且假设这些命令当前是AbstractButton,即JMenuItem、JButton。让我们看看Command接口及其实现。

1
2
3
public interface Command {
    public void execute();
}

实现部分请注意,Command是一个接口,而类仍然扩展了UI对象。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import javax.swing.JMenuItem;

public class TestCmd extends JMenuItem implements Command{

    public TestCmd() {
        super("Test");
        OneListener.getInstance().addCommand(this);
    }

    @Override
    public void execute() {
        System.out.println("HelloWorld");
    }
}

个人不喜欢在类的构造函数中调用OneListener,但为了本文的简洁性,我保留了这种方式。有很多不同的方法可以避免这样做。

因此TestCmd是一个JMenuItem,但也是一个Command,这就是OneListener所理解的。

由于这些命令的监听器也是OneListener,所有ActionEvents都被发送到那里,并且只从那里调用Command.execute。

所以现在您不必担心自己处于哪个监听器中。您唯一知道的是当execute被调用时,您需要执行自己的操作。

您可以从[这里]下载代码。

希望这对您有所帮助。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计