ctrl+z的JAVA实现,借助了命令模式(command pattern)
前些天学习<<JAVA与模式>>,到命令模式时,随带给了一个CTRL+Z案例的实现,想来学习编程这么久,CTRL+Z还没有认真实现过。
因此,借助JAVA与模式里面的源代码,自己对撤销和回退进行了实现(JAVA与模式书中代码有部分问题)。此次用到了命令模式,因为有界面,有按钮,有接收者,有发送者。
以下是类图,只为方便,未考虑UML细节规范。


package undoRedo; import java.awt.Frame;
import java.awt.event.*; public class MainFrame extends Frame { private static UndoableTextArea text;
private static ItsukyuQuatation panel; public MainFrame(String title)
{
super(title);
} public static void main(String[] args)
{ //构造可撤消的textArea
text = new UndoableTextArea("Your text here");
//构造panel
panel = new ItsukyuQuatation(text);
//构造frame
MainFrame frame = new MainFrame("测试undo和redo");
//增加窗体关闭事件
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
frame.add(panel);
frame.setSize(300,300);
frame.setVisible(true);
}
}
ItsukyuQuatation类:面板类,里面包括undo和redo两个按钮,类似于命令模式中的摇控器。实现了ActionListener接口。
package undoRedo; import java.awt.BorderLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; public class ItsukyuQuatation extends Panel implements ActionListener { private final Command undo;
private final Command redo; public ItsukyuQuatation(UndoableTextArea text)
{
this.setLayout(new BorderLayout());
Panel toolbar = new Panel();
undo = new UndoCommand(text);
redo = new RedoCommand(text);
undo.addActionListener(this);
redo.addActionListener(this);
toolbar.add(undo);
toolbar.add(redo); this.add(toolbar,"North");
this.add(text,"Center"); } public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
Command cmd = (Command)e.getSource();
cmd.execute();
} }
UndoableTextArea类:类似于命令模式中的电视机类。实现了StateEditable接口,因此该类具有可撤销和重做的功能。重载的storeState和restoreState即是把文本中的内容放到hashTable里去。
该类是最核心的类,实现ctrl+z的原理简单说就是UndoManger.edits是一个Vector动态数组,对每次的按键动作,都会存储一份当前的文本内容到数据。当点击undo按钮,
数组索引(UnoManager类的indexOfNextAdd变量)前移一位,取得前一状态的文本内容。点击redo按钮,数组索引后移一位,取后一状态的文本内容。但是各状态内容均未删或修改。
initUndoable()方法,如果用keyPressed事件,那么最近的状态未加到undoManager.edits列里。因此选用keyReleased事件。如果监听valueChanged事件,那么代码就
和JAVA与模式一书中一样,只能实现最近一次的编辑撤消。
package undoRedo; import java.awt.TextArea;
import java.awt.event.*;
import java.util.Hashtable;
import javax.swing.undo.*; import javax.swing.undo.StateEditable; public class UndoableTextArea extends TextArea implements StateEditable { private UndoManager undoManager;
private final static String KEY_STATE="UndoableTextAreaKey";
private StateEdit currentEdit;
boolean textChanged = false; public UndoableTextArea()
{
super();
initUndoable();
}
public UndoableTextArea(String string)
{
super(string);
initUndoable();
} //存储状态
public void storeState(Hashtable<Object, Object> hashTable) {
// TODO Auto-generated method stub
hashTable.put(KEY_STATE, this.getText());
} //还原状态
public void restoreState(Hashtable<?, ?> hashTable) {
// TODO Auto-generated method stub
Object data = hashTable.get(KEY_STATE);
if(data!=null)
{
this.setText((String)data);
}
} //撤销方法
public boolean undo()
{
try
{
undoManager.undo();
System.out.println("undo=" + undoManager.toString());
return true;
}catch(CannotUndoException e)
{
System.out.println("Can't undo");
}
return false;
} //重做方法
public boolean redo()
{
try
{
undoManager.redo();
System.out.println("redo=" + undoManager.toString());
return true;
}catch(CannotRedoException e)
{
System.out.println("Can't redo");
}
return false;
} private void initUndoable()
{
this.undoManager = new UndoManager(); this.currentEdit = new StateEdit(this); this.addKeyListener(new KeyAdapter()
{
/*
*
* 如果用keyPressed事件,那么最近的状态未加到undoManager.edits列里。
* 因此选用keyReleased事件。
*
public void keyPressed(KeyEvent event)
{
if(event.isActionKey())
{
//takeSnapshot();
}else
{
textChanged = true;
takeSnapshot();
}
}
*/
public void keyReleased(KeyEvent event)
{
if(event.isActionKey())
{
//takeSnapshot();
}else
{
textChanged = true;
takeSnapshot();
}
}
}); this.addFocusListener(new FocusAdapter()
{
public void focusLost(FocusEvent event)
{
//takeSnapshot();
}
}); } private void takeSnapshot()
{
if(textChanged)
{
this.currentEdit.end(); this.undoManager.addEdit(this.currentEdit); this.currentEdit = new StateEdit(this); System.out.println("takeSnapshot=" + undoManager.toString()); textChanged = false;
}
} }
Command抽象类:定义按钮,抽象方法 execute()
UndoCommand,RedoCommand均是Command类的实现,类似于命令模式中的具体按钮,调用接收者的方法进行实现。
package undoRedo; import java.awt.Button; public abstract class Command extends Button { public Command(String caption)
{
super(caption);
} public abstract void execute();
}
package undoRedo; public class UndoCommand extends Command { UndoableTextArea text; public UndoCommand(UndoableTextArea text)
{
super("Undo");
this.text = text;
} @Override
public void execute() {
// TODO Auto-generated method stub
text.undo();
} }
package undoRedo; public class RedoCommand extends Command { UndoableTextArea text; public RedoCommand(UndoableTextArea text)
{
super("Redo");
this.text = text;
} @Override
public void execute() {
// TODO Auto-generated method stub
text.redo();
} }
ctrl+z的JAVA实现,借助了命令模式(command pattern)的更多相关文章
- 设计模式 - 命令模式(command pattern) 多命令 具体解释
命令模式(command pattern) 多命令 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.csdn.ne ...
- 设计模式 - 命令模式(command pattern) 具体解释
命令模式(command pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 命令模式(command pattern) : 将请求封装成对 ...
- 设计模式 - 命令模式(command pattern) 宏命令(macro command) 具体解释
命令模式(command pattern) 宏命令(macro command) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考: 命名模式(撤销) ...
- 乐在其中设计模式(C#) - 命令模式(Command Pattern)
原文:乐在其中设计模式(C#) - 命令模式(Command Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 命令模式(Command Pattern) 作者:webabcd ...
- 设计模式 - 命令模式(command pattern) 撤销(undo) 具体解释
命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.cs ...
- 二十四种设计模式:命令模式(Command Pattern)
命令模式(Command Pattern) 介绍将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可取消的操作. 示例有一个Message实体类,某个 ...
- 设计模式-15命令模式(Command Pattern)
1.模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使 ...
- 《JAVA设计模式》之命令模式(Command)
在阎宏博士的<JAVA与模式>一书中开头是这样描述命令(Command)模式的: 命令模式属于对象的行为模式.命令模式又称为行动(Action)模式或交易(Transaction)模式. ...
- 设计模式----行为型模式之命令模式(Command Pattern)
下面来自head first设计模式的命令模式一章节. 定义 将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 类图 注: 1. ...
- 设计模式(六):控制台中的“命令模式”(Command Pattern)
今天的博客中就来系统的整理一下“命令模式”.说到命令模式,我就想起了控制台(Console)中的命令.无论是Windows操作系统(cmd.exe)还是Linux操作系统(命令行式shell(Comm ...
随机推荐
- centos 6.3 64位安装php5.5及配置tengine
PHP 用到的工具包: yum install gd-devel libjpeg-devel libpng-devel freetype-devel libxml2-devel curl-devel ...
- lucene解决全文检索word2003,word2007的办法
在上一篇文章中 ,lucene只能全文检索word2003,无法检索2007,并且只能加载部分内容,无法加载全文内容.为解决此问题,找到了如下方法 POI 读取word (word 2003 和 wo ...
- 2016031401 - ubuntu显示桌面快捷键
ubuntu显示桌面快捷键设置 步骤如下:系统设置->键盘->快捷键->窗口->最小化窗口 个人设置的是super+D,super就是window下的win键.
- pyes-elasticsearch的python客户端使用笔记
elasticsearch入门: http://www.qwolf.com/?p=1387 一.重要的概念 http://834945712.iteye.com/blog/1915432 这篇文章很 ...
- 第 6 章 抽象工厂模式【Abstract Factory Pattern】
以下内容出自:<<24种设计模式介绍与6大设计原则>> 好了,我们继续上一节课,上一节讲到女娲造人,人是造出来了,世界时热闹了,可是低头一看,都 是清一色的类型,缺少关爱.仇恨 ...
- bzoj 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 曼哈顿生成树
大致题意:统计平面上由曼哈顿距离小于等于c的点对组成联通块的个数. 曼哈顿生成树的模板题.有关讲解:http://blog.csdn.net/acm_cxlove/article/details/88 ...
- 【BZOJ 1096】 [ZJOI2007]仓库建设 (斜率优化)
1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3940 Solved: 1736 Description ...
- init进程 && 解析Android启动脚本init.rc && 修改它使不启动android && init.rc中启动一个sh文件
Android启动后,系统执行的第一个进程是一个名称为init 的可执行程序.提供了以下的功能:设备管理.解析启动脚本.执行基本的功能.启动各种服务.代码的路径:system/core/init,编译 ...
- bzoj1023
研究了一下仙人掌首先,仙人掌虽然不是树,但却有很强的树的既视感如果把每个环都看做一个点,那么他就是一棵树当然这不能直接缩环,因为环和环可以有一个交点如果是树,求直径都会做,令f[i]表示i到子树的最长 ...
- 推荐一个Xcode插件: KSImageNamed (自动补全图片文件名称, 并显示图片大小)
http://www.csdn.net/article/2014-05-04/2819586-the-best-xcode-plugins 5. KSImageNamed KSImageNamed是一 ...