| | | | | | | [文章信息] | | | 作者: | 陶刚编译 | | 时间: | 2005-02-17 | | 出处: | 天极网 | | 责任编辑: | 方舟 | |
| [文章导读] | | | 命令行为模式是我们可以使用的一种简单模式,它在行为概念的具体化和撤销行为方面显得尤其有益 | |
| |
|
| | | |
|
|
|
|
|
建立GUI
该程序的GUI由Form1表现,它包含了一个图像(image)控件,在该控件中有一个球的位图。该窗体还包含了一个对象集合,我把这个集合作为先前命令的堆栈。通过把每条命令添加到该集合的末尾,以及从集合末尾弹出命令,我可以相反地跟踪命令的执行过程。从本质上来说,该集合扮演了堆栈的角色。我在命令执行之后压入(push)命令,弹出(pop)命令调用Undo操作。
为了演示Undo操作,我定义了Edit|Undo菜单和Edit|Rewind操作。Undo从堆栈中弹出一条命令并调用Undo。Rewind弹出所有命令,在每个命令上调用Undo。列表2包含了Form1的代码。
列表2
Option Explicit
Private stack As Collection Private Const MOVEMENT_AMOUNT As Integer = 50
Private Sub AboutMenu_Click() Const About As String = "Command Pattern Demo" + vbCrLf + _ "Copyright (c) 2004. All Rights Reserved" + vbCrLf + _ "Written By Paul Kimmel. pkimmel@softconcepts.com"
MsgBox About, vbInformation + vbOKOnly, "About"
End Sub
Private Sub ExitMenu_Click() End End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case vbKeyBack UndoCommand Case vbKeyLeft Call ProcessCommand(New LeftCommand) Case vbKeyUp Call ProcessCommand(New UpCommand) Case vbKeyRight Call ProcessCommand(New RightCommand) Case vbKeyDown Call ProcessCommand(New DownCommand) End Select End Sub
Private Function PopStack() As ICommand On Error GoTo Catch Debug.Print "Stack count: " & stack.Count If (stack.Count = 0) Then Beep Set PopStack = Nothing Exit Function End If
Set PopStack = stack.Item(stack.Count) Call stack.Remove(stack.Count) Exit Function Catch: Debug.Print Err.Description Set PopStack = Nothing End Function
Private Sub PushStack(ByVal command As ICommand) On Error GoTo Catch Call stack.Add(command) Debug.Print "Stack count: " & stack.Count Exit Sub Catch: Debug.Print Err.Description End Sub
Public Sub UndoCommand() Dim command As ICommand Set command = PopStack() If (command Is Nothing) Then Exit Sub command.Undo End Sub
Private Sub ProcessCommand(ByVal command As ICommand) Set command.Form = Me command.Execute Call PushStack(command) End Sub
Public Sub MoveDown() Debug.Print "Moving Down" If (Image1.Top > Height) Then Image1.Top = 0 - Image1.Height + MOVEMENT_AMOUNT Else Image1.Top = Image1.Top + MOVEMENT_AMOUNT End If End Sub
Public Sub MoveUp() Debug.Print "Moving Up" If (Image1.Top + Image1.Height < 0) Then Image1.Top = Height - MOVEMENT_AMOUNT Else Image1.Top = Image1.Top - MOVEMENT_AMOUNT End If End Sub
Public Sub MoveLeft() Debug.Print "Moving Left" If (Image1.Left + Image1.Width < 0) Then Image1.Left = Width - MOVEMENT_AMOUNT Else Image1.Left = Image1.Left - MOVEMENT_AMOUNT End If End Sub
Public Sub MoveRight() Debug.Print "Moving Right" If (Image1.Left > Width) Then Image1.Left = 0 - Image1.Width + MOVEMENT_AMOUNT Else Image1.Left = Image1.Left + MOVEMENT_AMOUNT End If End Sub
Private Sub Form_Load() Set stack = New Collection End Sub
Private Sub RewindMenu_Click() While stack.Count > 0 UndoCommand Wend End Sub
Private Sub UndoMenu_Click() Call UndoCommand End Sub | 下一步,我通过把窗体的KeyPreview属性设置为True并建立与该按键相关的命令对象,把有关的方向箭头按键与每条命令关联起来。例如vbKeyUp应该建立一个UpCommand对象。接着我处理这些命令(我也可以使用工厂创建型模式把命令对象的创建过程移动到命令类的内部)。
ProcessCommand被定义为把Form1的指针赋予某个命令的Form属性、执行该命令并把该命令压入集合堆栈中。你没有必要实现一个堆栈,但是如果你没有跟踪命令执行的次序,那么使用Undo操作是不可能的。
图1显示的UML模型显示了示例程序中不同的类之间的关系。
 图1:命令中的类:描述我们的命令模式中关系的UML类图表 |
|
|
|
|
|
|
|
|
|