`

命令模式--撤销恢复

    博客分类:
  • 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();
		}
	}
}

 

  • 大小: 7.8 KB
0
4
分享到:
评论
1 楼 snowdream 2011-11-25  
写的很不错,感谢分享。

相关推荐

    设计模式专题之(十四)命令模式---设计模式命令模式示例代码(python--c++)

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在本专题中,我们将深入探讨命令模式,并通过Python和C++两种...

    c#代码介绍23种设计模式-15命令模式(附代码)

    命令模式的实现可以提供命令的撤销和恢复功能。 2. 命令模式的结构 既然,命令模式是实现把发出命令的责任和执行命令的责任分割开,然而中间必须有某个对象来帮助发出命令者来传达命令,使得执行命令的接收者可以...

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    - 命令模式(Command):将请求封装为一个对象,以便使用不同的请求、队列请求、或者支持可撤销的操作。 - 解释器模式(Interpreter):给定一种语言,定义它的文法表示,并提供一个解释器来处理这种语言中的句子...

    设计模式之命令模式

    命令模式是一种行为设计模式,它将请求封装为一个对象,使得可以使用不同的请求对客户进行参数化,同时支持可撤销的操作、请求队列和请求日志。这种模式的核心在于将发出命令的动作与执行命令的实体分离,使得系统...

    vim命令模式下使用

    ### vim命令模式下的关键知识点 #### 一、vi(vim)简介与背景 - **vi**(Visual Interface)是一款在Unix及其衍生系统中广泛使用的文本编辑器。 - **vim**(vi IMproved)是对vi的增强版本,包含了更多实用功能,并...

    命令模式代码demo

    命令模式是一种设计模式,它将请求封装为一个对象,从而使我们能使用不同的请求、队列或者日志请求,以及支持可撤销的操作。在本代码demo中,我们将深入探讨这一模式的实现及其应用。 命令模式的核心思想是解耦调用...

    [行为型模式]命令模式的理解

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在软件工程中,这种模式常用于解耦发出命令的对象(调用者)与...

    git命令大全-git-cheatsheet.docx

    - **用途**: 丢弃工作目录中所有的更改,恢复到最近一次提交的状态。 - **参数**: `--hard` 表示强制重置,`HEAD` 是最近一次提交的引用。 - **示例**: `git reset --hard HEAD`会将所有未提交的更改丢弃。 ##### ...

    设计模式之命令模式Java实现

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在Java中实现命令模式,我们可以按照以下步骤进行: 1. **定义...

    23种 设计模式---面向对象的基本原则

    - 命令模式(Command):将一个请求封装为一个对象,以便使用不同的请求、队列或者日志请求,支持可撤销的操作。 - 解释器模式(Interpreter):给定一种语言,定义它的文法表示,并提供一个解释器来处理该语言中...

    设计模式-在线

    命令模式适用于需要参数化对象以支持操作的撤销、恢复和队列操作等。 另外,从提供的文件内容来看,还有其他一些设计模式的名称被提及,如适配器模式(Adapter)、桥接模式(Bridge)、组合模式(Composite)、外观...

    命令模式实现事务补偿2

    **命令模式** 是设计模式的一种,它将请求封装为一个对象,使得我们可以参数化不同请求,队列或者记录请求日志,以及支持可撤销的操作。在事务补偿的场景下,每个命令代表一个操作,当这个操作执行失败时,可以有...

    MAX命令翻译[参考].pdf

    - EDIT:编辑命令,包括撤消、恢复、保存所选择的对象等。 - SAVE SELECTED:保存所选择的对象,用于快速保存当前选择的对象。 - REDO:恢复命令,用于恢复之前的操作。 2. 对象操作命令: - XREF OBJECTS:...

    HeadFirst 命令模式 风扇课本实现错误代码及利用栈的解决办法

    在软件设计模式中,命令模式是一种行为设计模式,它将请求封装为一个对象,使得你可以用不同的请求参数化其他对象,同时支持可撤销的操作。在《HeadFirst JAVA设计模式》一书中,风扇命令是一个典型的例子,但根据...

    Java设计模式-图解-附代码

    - 命令模式:将请求封装为一个对象,以便使用不同的请求、队列请求或日志请求,同时也支持可撤销的操作。 - 解释器模式:给定一个语言,定义它的文法表示,并提供一个解释器来处理这种语言中的句子。 - 迭代器...

    后端-设计模式-java-精讲

    - **命令模式**: 将一个请求封装为一个对象,从而使用户可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 - **备忘录模式**: 在不破坏封装性的前提下,捕获一个对象的内部...

    设计模式精解-GoF 23种设计模式解析.pdf

    - **定义**:命令模式将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 - **应用场景**:当需要将请求封装为对象时,可以使用此模式。 - **优...

    《设计模式--基于C#的工程化实现及扩展》.(王翔)

    命令模式将请求封装为一个对象,使得可以使用不同的请求、队列请求、支持撤销操作。C#中的方法调用实际上就是一种命令模式的体现。 十二、组合模式(Composite) 组合模式允许你将对象组合成树形结构来表现“整体-...

    java设计模式-备忘录模式

    例如,命令模式可以用来记录操作序列,而备忘录模式可以保存这些操作序列中的每一步状态,以便于撤销或重做。同时,备忘录模式还可以用于实现事务管理,当事务需要回滚时,可以使用备忘录恢复到事务开始前的状态。 ...

Global site tag (gtag.js) - Google Analytics