use*_*545 4 swing design-patterns jbutton command-pattern jmenuitem
所以,我正在使用 Swing 库开发一个程序,我显然有按钮和菜单项。其中一些应该做同样的事情,我认为使用命令模式应该是这样做的方式,例如我有一个“保存”按钮和一个“保存”菜单项,他们必须实现相同的保存算法. 命令模式似乎没问题,但我不知道谁是接收者。难道一个命令不应该在一个实现某种“接收器接口”的对象上工作,这样你就可以在不同的接收器上使用不同的命令来任意耦合它们吗?看起来我的模式实现中没有“接收器”。我的另一个疑问是是否应该将命令实现为单例,
谢谢你。
“我显然有按钮和菜单项。其中一些应该做同样的事情,”
正如@nIcEcOw 所指出的,这就是Actions 的用途。这个答案恰恰说明了这一点。
Action 可用于将功能和状态与组件分离。例如,如果您有两个或多个执行相同功能的组件,请考虑使用 Action 对象来实现该功能。Action 对象是一个动作侦听器,它不仅提供动作事件处理,还提供动作事件触发组件(例如工具栏按钮、菜单项、通用按钮和文本字段)状态的集中处理。操作可以处理的状态包括文本、图标、助记符、启用和选定状态。

安只有三个Actions。打开、保存和新建。每个Action都有要执行的ActionCommand, 和icon, 和 操作。无论是JMenuItem和JToolBar按钮共享相同的Action和做同样的事情。这是您可以运行的代码。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class ActionTest {
public ActionTest() {
ImageIcon openIcon = new ImageIcon(
ActionTest.class.getResource("/resources/image/open.gif"));
ImageIcon saveIcon = new ImageIcon(
ActionTest.class.getResource("/resources/image/save.gif"));
ImageIcon newIcon = new ImageIcon(
ActionTest.class.getResource("/resources/image/new.gif"));
Action openAction = new AbstractAction("Open", openIcon) {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Open File");
}
};
Action saveAction = new AbstractAction("Save", saveIcon) {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Save File");
}
};
Action newAction = new AbstractAction("New", newIcon) {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("New File");
}
};
JMenuItem openMenuItem = new JMenuItem(openAction);
JMenuItem saveMenuItem = new JMenuItem(saveAction);
JMenuItem newMenuItem = new JMenuItem(newAction);
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.add(openMenuItem);
fileMenu.add(saveMenuItem);
fileMenu.add(newMenuItem);
menuBar.add(fileMenu);
JToolBar toolBar = new JToolBar();
toolBar.add(Box.createHorizontalGlue());
toolBar.setBorder(new LineBorder(Color.LIGHT_GRAY, 1));
toolBar.add(newAction);
toolBar.add(openAction);
toolBar.add(saveAction);
JFrame frame = new JFrame("Toolbar and Menu Test");
frame.setJMenuBar(menuBar);
frame.add(toolBar, BorderLayout.PAGE_START);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ActionTest();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
正如上述教程中的引用所述,您可以做的不仅仅是将图像和操作命令添加到Action. 您可以使用它来设置助记符和加速器。这是一个自定义Action类,需要
和一个关键的加速器。
private class MyAction extends AbstractAction {
String name;
public MyAction(String name, Icon icon) {
super(name, icon);
this.name = name;
}
public MyAction(String name, Icon icon, String desc,
Integer mnemonic, KeyStroke accelorator) {
super(name, icon);
putValue(Action.SHORT_DESCRIPTION, desc);
putValue(Action.MNEMONIC_KEY, mnemonic);
putValue(Action.ACCELERATOR_KEY, accelorator);
this.name = name;
}
@Override
public void actionPerformed(ActionEvent e) {
switch (name) {
case "Open":
System.out.println("Open");
break;
case "New":
System.out.println("New");
break;
case "Save":
System.out.println("Save");
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)这是这个的实例化 Action
Action newAction = new MyAction("New", newIcon,
"Creates a new file",
new Integer(KeyEvent.VK_N),
KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
Run Code Online (Sandbox Code Playgroud)
这是新的结果。您将actionCommand在菜单中看到,以及关键助记符和加速器、工具提示,并且您将看到 jtoolbar 按钮具有相同的特征。您还将在最终代码中看到,一旦创建了组件,就不会出现一次。所有你要做的是添加Action到JToolBar和JMenu,让他们创造了神奇。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ActionInterfaceDemo extends JFrame {
public ActionInterfaceDemo() {
ImageIcon openIcon = new ImageIcon(ActionInterfaceDemo.class.getResource("/resources/image/open.gif"));
ImageIcon saveIcon = new ImageIcon(ActionInterfaceDemo.class.getResource("/resources/image/save.gif"));
ImageIcon newIcon = new ImageIcon(ActionInterfaceDemo.class.getResource("/resources/image/new.gif"));
Action openAction = new MyAction("Open", openIcon,
"Opens a file",
new Integer(KeyEvent.VK_O),
KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
Action saveAction = new MyAction("Save", saveIcon,
"Saves a file",
new Integer(KeyEvent.VK_S),
KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
Action newAction = new MyAction("New", newIcon,
"Creates a new file",
new Integer(KeyEvent.VK_N),
KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
setJMenuBar(menuBar);
menuBar.add(fileMenu);
fileMenu.add(newAction);
fileMenu.add(openAction);
fileMenu.add(saveAction);
JToolBar toolBar = new JToolBar("Alignment");
toolBar.setBorder(BorderFactory.createLineBorder(Color.BLUE));
toolBar.add(Box.createHorizontalGlue());
toolBar.add(newAction);
toolBar.add(openAction);
toolBar.add(saveAction);
add(toolBar, BorderLayout.PAGE_START);
add(new JScrollPane(new TextArea(10, 40)), BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Action Interface Demo");
pack();
setLocationByPlatform(true);
setVisible(true);
}
private class MyAction extends AbstractAction {
String name;
public MyAction(String name, Icon icon) {
super(name, icon);
this.name = name;
}
public MyAction(String name, Icon icon, String desc,
Integer mnemonic, KeyStroke accelorator) {
super(name, icon);
putValue(Action.SHORT_DESCRIPTION, desc);
putValue(Action.MNEMONIC_KEY, mnemonic);
putValue(Action.ACCELERATOR_KEY, accelorator);
this.name = name;
}
@Override
public void actionPerformed(ActionEvent e) {
switch (name) {
case "Open":
System.out.println("Open");
break;
case "New":
System.out.println("New");
break;
case "Save":
System.out.println("Save");
break;
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new ActionInterfaceDemo();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
更好地解释Action和命令模式的关系
命令模式是一种常用的模式,它将方法调用或类似动作的代码封装到单个类中。当您有多个调用程序用于单个操作(例如,按钮和菜单项可能执行相同的操作)时,能够将一个方法(或多个方法)打包到一个类中的优势变得明显。
在 Swing 和 Borland Delphi 编程中,an
Action是命令对象。除了执行所需命令的能力之外,Action还可以具有关联的图标、键盘快捷键、工具提示文本等。工具栏按钮或菜单项组件可以仅使用Action对象来完全初始化。
所以基本上 Swing通过使用命令模式的概念Actions
至于OP的问题
“命令模式似乎没问题,但我不知道谁是接收者。”
至于接收器,wiki 使用文本编辑器作为示例,并将接收器定义为这样
Receiver, Target Object:即将被复制、粘贴、移动等的对象。接收者对象拥有命令的execute方法调用的方法。接收器通常也是目标对象。例如,如果接收者对象是一个游标并且该方法被称为 moveUp,那么人们会期望游标是 moveUp 操作的目标。另一方面,如果代码是由命令对象本身定义的,则目标对象将是一个完全不同的对象。
命令模式的主要组件如下所述
与命令模式相关的四个术语是命令、接收者、调用者和客户端。
Client、Source、Invoker:被点击的按钮、工具栏按钮或菜单项,用户按下的快捷键。
所以把它们放在一起:
actionPerformed依次调用它该wiki文章是一个Java的例子很好看