该例子来自阎宏提供的例子程序,以画线为例:
命令接口Command:
package com.javapatterns.command.drawlines;
//命令接口
public interface Command {
abstract public void execute();// 执行操作
abstract public void unexecute();// 取消操作
abstract public boolean canExecute();//是否允许执行操作
abstract public boolean canUnexecute();//是否允许取消操作
}
添加线命令类AddLineCommand:
/* Generated by Together */
package com.javapatterns.command.drawlines;
//添加线命令类
public class AddLineCommand implements Command {
private Drawing drawing;// 画布
private Line line;//直线
public AddLineCommand(Drawing targetDrawing, Line newLine) {
drawing = targetDrawing;
line = newLine;
}
//执行将直线添加到画布的操作
public void execute() {
drawing.add(line);
}
//执行将直线从画布中移除的操作
public void unexecute() {
drawing.remove(line);
}
public boolean canExecute() {
return true;
}
public boolean canUnexecute() {
return true;
}
}
命令集合类CommandList:
package com.javapatterns.command.drawlines;
import java.util.Stack;
//命令集合类,负责存储执行过的命令和撤销执行的命令
public class CommandList {
private Stack<Command> executedCommands = new Stack<Command>();
private Stack<Command> unexecutedCommands = new Stack<Command>();
private void _execute(Command command) {
command.execute();//执行具体的命令
executedCommands.push(command);//记录执行的命令
}
//执行命令
public void execute(Command command) {
unexecutedCommands.removeAllElements();
_execute(command);
}
//撤销执行,每执行一次该方法,将从最近的一次操作开始撤销
public void unexecute() {
Command command = (Command) executedCommands.pop();//出栈最后一次执行命令
command.unexecute();//撤销该命令的执行
unexecutedCommands.push(command);//记录撤销的命令
}
//恢复执行,每执行一次该方法,将从最近的一次操作开始撤销
public void reexecute() {
Command command = (Command) unexecutedCommands.pop();//出栈最后一次撤销命令
_execute(command);//重新执行
}
//清空撤销和恢复的缓存
public void reset() {
executedCommands.removeAllElements();
unexecutedCommands.removeAllElements();
}
//是否允许撤销命令,没有执行过命令就不存在撤销
public boolean canUnexecuteCommand() {
return !executedCommands.empty();
}
//是否允许恢复命令,没有撤销过命令就不存在恢复
public boolean canReexecuteCommand() {
return !unexecutedCommands.empty();
}
}
画布Drawing:
/* Generated by Together */
package com.javapatterns.command.drawlines;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Enumeration;
import java.util.Vector;
//(接收者,负责具体实施和执行一个请求)画布,可以在该画布上画任意条直线
public class Drawing extends Canvas implements MouseListener,
MouseMotionListener {
private static final long serialVersionUID = -4887753465176351050L;
private SimpleDraw applet;//应用程序
private Vector<Line> lines;//线集合
private Point startPosition;//画线开始位置
private Point mousePosition;//鼠标位置
private boolean mousePressed;//鼠标是否按下
//构造方法,初始化属性信息
public Drawing(SimpleDraw owner) {
applet = owner;
lines = new Vector<Line>();
mousePressed = false;//默认鼠标未按下
setBackground(Color.GREEN);//设置画布背景色
addMouseListener(this);//添加鼠标监听器,自己实现了该接口
addMouseMotionListener(this);//添加鼠标移动事件的侦听器,自己实现了该接口
}
//添加一条线(行动方法)
public void add(Line line) {
lines.addElement(line);
repaint();
}
//删除一条线(行动方法)
public void remove(Line line) {
lines.removeElement(line);
repaint();
}
public void paint(Graphics graphics) {
Enumeration<Line> enumeration = lines.elements();
Line currentLine;
while (enumeration.hasMoreElements()) {
currentLine = (Line) (enumeration.nextElement());
currentLine.paint(graphics);
}
if (mousePressed) {
graphics.drawLine(startPosition.x, startPosition.y,
mousePosition.x, mousePosition.y);
}
}
//鼠标按键在组件上单击(按下并释放)时调用
public void mouseClicked(MouseEvent event) {
}
//鼠标进入到组件上时调用
public void mouseEntered(MouseEvent event) {
}
//鼠标离开组件时调用
public void mouseExited(MouseEvent event) {
}
//鼠标按键在组件上按下时调用
public void mousePressed(MouseEvent event) {
mousePressed = true;//设置鼠标为按下状态
startPosition = event.getPoint();//记录直线的开始位置
}
//鼠标按钮在组件上释放时调用
public void mouseReleased(MouseEvent event) {
if (!event.getPoint().equals(startPosition)) {//两点不重合
Line line = new Line(startPosition, event.getPoint());//创建直线
AddLineCommand command = new AddLineCommand(this, line);//创建添加直线的一个命令
applet.execute(command);//请求者请求命令的执行
}
mousePressed = false;
}
public void mouseDragged(MouseEvent event) {
mousePosition = event.getPoint();
repaint();
}
public void mouseMoved(MouseEvent event) {
}
}
直线Line:
package com.javapatterns.command.drawlines;
import java.awt.Point;
import java.awt.Graphics;
public class Line {
private Point start;
private Point end;
public Line( Point startPos, Point endPos ) {
start = startPos;
end = endPos;
}
public void paint( Graphics graphics ) {
graphics.drawLine( start.x, start.y, end.x, end.y );
}
}
容器SimpleDraw:
/* Generated by Together */
package com.javapatterns.command.drawlines;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
// 请求者(负责调用命令对象执行请求)
public class SimpleDraw extends Applet implements ActionListener {
private static final long serialVersionUID = 2317696438230972428L;
private Drawing drawing;// 画布
private CommandList commands;// 命令集合
private Button undoButton;// 撤销按钮
private Button redoButton;// 恢复按钮
private Button resetButton;// 清空撤销和恢复按钮
public void init() {
Panel panel = new Panel();// 面板
commands = new CommandList();// 初始化命令集合
setLayout(new BorderLayout());// 设置布局
drawing = new Drawing(this);// 初始化画布
add("Center", drawing);
undoButton = new Button("撤销");// 初始化撤销按钮
redoButton = new Button("恢复");// 初始化恢复按钮
resetButton = new Button("重置");
undoButton.addActionListener(this);// 添加按钮监听器
redoButton.addActionListener(this);// 添加按钮监听器
resetButton.addActionListener(this);// 添加按钮监听器
panel.add(undoButton);
panel.add(redoButton);
panel.add(resetButton);
add("South", panel);
updateButtons();// 初始化按钮状态
}
public void execute(Command command) {
commands.execute(command);// 执行命令
updateButtons();
}
// 更新按钮状态(根据是否能够undo撤销或者是否能够redo恢复)
private void updateButtons() {
undoButton.setEnabled(commands.canUnexecuteCommand());
redoButton.setEnabled(commands.canReexecuteCommand());
}
// 当点击撤销按钮或者恢复按钮时出发该方法执行
public void actionPerformed(ActionEvent event) {
if (event.getSource() == undoButton) {
commands.unexecute();
updateButtons();
}else if (event.getSource() == redoButton) {
commands.reexecute();
updateButtons();
}else if (event.getSource() == resetButton) {
commands.reset();
updateButtons();
}
}
}