命令模式--撤销恢复

标签: Java

该例子来自阎宏提供的例子程序,以画线为例:

 命令接口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();
		}
	}
}

 

版权声明:本文为iteye_5724原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/iteye_5724/article/details/82033535