一、介绍
还是先来看一下《研磨设计模式》的定义——将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
命令模式的本质——封装请求。
封装请求是什么意思呢?其实在
Java中随处可见。最简单的就像在Swing中,每次触发一个事件,都会产生一个相应的事件对象,这个事件对象封装了这个事件所有的参数,我们通过这个事件对象来对这个事件进行处理。同样的,我们每次触发了一个异常,这个异常的所有参数、包括堆栈信息都会被封装在一个异常对象中,它代表这个异常事件本身,然后由我们来处理或抛出。
这样讲来,命令模式不过是将一个请求封装起来罢了。然而,这里面却大有文章可作。
二、我的实现
我们在写文档的时候,作为命令对象接受者的文本文档,它可能接收的是我们在键盘的一个简单的字符输出的命令,有可能接收的是改变光标位置的命令,也可能接收的是我们的删除命令;在进行这些操作的时候,也有可能接收的是我们的撤销操作命令。假设我们的文本文档只能接收这些命令。
现在我们用命令模式封装这些命令模拟一下在文档上进行文本操作的过程。1、首先我们有一个命令接口,如下:
复制代码
1 public interface Command {
2
3 //处理
4 public void execute();
5 //恢复
6 public void recover();
7 }
复制代码
2、按照计算机的原理,我们对文本操作的命令应该是键盘或鼠标将命令发送给外设驱动,外设驱动发送给CPU,然后CPU发送给显卡,显卡发送给屏幕,进行显示。这里我们省略繁琐的命令传递,将命令直接交给屏幕。由于对屏幕的操作都是属于屏幕本身的操作,这里不用接口了,构建屏幕类如下:
复制代码
1 public class Screen {
2
3 //设置为单例
4 private static Screen screen = new Screen();
5 //当前屏幕内容
6 private StringBuilder screenContent = new StringBuilder();
7 //此次刷新前屏幕内容
8 private StringBuilder oldContent = screenContent;
9 //屏幕光标位置,默认为屏幕内容最尾
10 private int pos = screenContent.length();
11
12 private Screen(){
13 }
14
15 public static Screen getInstance(){
16 return screen;
17 }
18 //指定位置插入字符
19 public void insert(int pos, String content){
20 oldContent = screenContent;
21 screenContent.insert(pos, content);
22 this.pos = pos + content.length();
23 }
24 //插入字符
25 public void insert(String content){
26 this.insert(pos,content);
27 }
28
29 //返回当前光标位置
30 public int getPos()
31 {
32 return pos;
33 }
34
35 //设置当前光标位置
36 public void setPos(int pos)
37 {
38 this.pos = pos;
39 }
40
41 //返回屏幕内容
42 public String getScreenContent()
43 {
44 return screenContent.toString();
45 }
46 //可用来覆盖屏幕内容
47 public void setScreenContent(String src)
48 {
49 oldContent = screenContent;
50 this.screenContent = new StringBuilder(src);
51 pos = src.length();
52 }
53
54 //返回此次刷新前屏幕内容
55 public String getOldContent()
56 {
57 return oldContent.toString();
58 }
59
60 //清空屏幕
61 public void clear(){
62 oldContent = screenContent;
63 screenContent = new StringBuilder();
64 pos = 0;
65 }
66
67 //输出
68 public void outPut(){
69 System.out.println(new SimpleDateFormat("hh:mm:ss").format(new Date())+",当前光标位置:"+pos+",屏幕刷新输出:"+screenContent);
70 }
71
72
73 }
复制代码
3、好了,我们来构建第一个书写命令,如下:
复制代码
1 public class WriteCommand implements Command {
2 // 写之前屏幕的内容
3 private String oldScreenContent;
4 //移动光标前光标位置
5 private int oldPos;
6 //要写的
7 private String content;
8 private Screen screen = Screen.getInstance();
9
10 public void setScreen(Screen screen)
11 {
12 this.screen = screen;
13 }
14
15 //构造方法传入要写的内容
16 public WriteCommand(String str)
17 {
18 this.content = str;
19 }
20