前言
Undo,Redo是编辑环境里常见的并且非常重要的功能,下面介绍【命令模式】在Flex/AS3下的实现。
ICommand接口
定义ICommand接口,其中Execute和UnExecute是相反的2个操作,Title属性用于命令显示,例如显示在操作历史列表里。
package cwn.wb.ui.core.command
{
import cwn.core.IDispose;
public interface ICommand extends IDispose
{
function get Title():String
function Execute():void
function UnExecute():void
}
}
CommandBase基类
CommandBase类主要实现ICommand接口,所有Command类都将继承CommandBase类。
package cwn.wb.ui.core.command
{
import cwn.core.IDispose;
public class CommandBase implements ICommand
{
public function CommandBase()
{
}
//===================ICommand========================
protected var _Title:String;
public function get Title():String
{
return _Title;
}
public function Execute():void
{
throw new Error("Not implementation.");
}
public function UnExecute():void
{
throw new Error("Not implementation.");
}
//========================IDispose==========================
private var _Disposed:Boolean = false;
protected function Disposing():void
{
}
public function Dispose():void
{
if (_Disposed)
return;
Disposing();
_Disposed = true;
}
}
}
AddCommand类
AddCommand用于处理向界面容器添加子元件的操作,定义如下:
package cwn.wb.ui.core.command
{
import mx.core.UIComponent;
public class AddCommand extends CommandBase
{
private var _Parent:UIComponent;
private var _Target:UIComponent;
private var _Index:int;
public function AddCommand(parent:UIComponent, target:UIComponent)
{
_Parent = parent;
_Target = target;
_Index = _Parent.numChildren;
if (_Parent.contains(_Target))
_Index = _Parent.getChildIndex(_Target);
_Title = "添加" + _Target.name;
}
override public function Execute():void
{
if(_Parent.contains(_Target))
return;
_Parent.addChildAt(_Target, Math.min(_Parent.numChildren, _Index));
}
override public function UnExecute():void
{
if(!_Parent.contains(_Target))
return;
_Parent.removeChild(_Target);
}
override protected function Disposing():void
{
_Parent = null;
_Target = null;
super.Disposing();
}
}
}
DeleteCommand类
DeleteCommand用于处理向界面容器删除子元件的操作,效果与AddCommand相反,定义如下:
package cwn.wb.ui.core.command
{
import mx.core.UIComponent;
public class DeleteCommand extends CommandBase
{
private var _Parent:UIComponent;
private var _Target:UIComponent;
private var _Index:int;
public function DeleteCommand(parent:UIComponent, target:UIComponent)
{
_Parent = parent;
_Target = target;
_Index = _Parent.numChildren;
if (_Parent.contains(_Target))
_Index = _Parent.getChildIndex(_Target);
_Title = "删除" + _Target.name;
}
override public function Execute():void
{
if (!_Parent.contains(_Target))
return;
_Parent.removeChild(_Target);
}
override public function UnExecute():void
{
if (_Parent.contains(_Target))
return;
_Parent.addChildAt(_Target, Math.min(_Parent.numChildren, _Index));
}
override protected function Disposing():void
{
_Parent = null;
_Target = null;
super.Disposing();
}
}
}
EditCommand类
EditCommand用于处理元件的属性编辑操作,定义如下:
package cwn.wb.ui.core.command
{
import mx.core.UIComponent;
public class EditCommand extends CommandBase
{
private var _Property:String;
private var _Target:Object;
private var _OldValue:Object;
private var _NewValue:Object;
public function EditCommand(property:String, target:Object, oldValue:Object, newValue:Object)
{
_Property = property;
_Target = target;
_OldValue = oldValue;
_NewValue = newValue;
_Title = "编辑" + _Property;
}
override public function Execute():void
{
_Target[_Property] = _NewValue;
}
override public function UnExecute():void
{
_Target[_Property] = _OldValue;
}
override protected function Disposing():void
{
_Target = null;
_OldValue = null;
_NewValue = null;
super.Disposing();
}
}
}
例子:编辑宽度
var edit:EditCommand = new EditCommand("width", target, target.width, 500);
CommandManager类
添加,删除,编辑3个主要命令已经定义完成,现在要定义一个命令管理的类对命令进行管理,集中调用,其中Undo,Redo操作都在该类实现。
package cwn.wb.ui.core.command
{
import cwn.core.DisposeUtil;
import flash.events.EventDispatcher;
import mx.collections.ArrayCollection;
import mx.core.UIComponent;
public class CommandManager extends EventDispatcher
{
private static var g_Created:Boolean = false;
public static var Instance:CommandManager = new CommandManager();
public function CommandManager()
{
super();
if (g_Created)
throw new Error("Singleton class. Please use Instance static filed.");
g_Created = true;
}
//======================命令管理:Undo,Redo=============================
private var _UndoList:ArrayCollection = new ArrayCollection();
private var _RedoList:ArrayCollection = new ArrayCollection();
public function get CanRedo():Boolean
{
return _RedoList.length > 0;
}
public function get CanUndo():Boolean
{
return _UndoList.length > 0;
}
public function Redo():void
{
if (!CanRedo)
return;
var command:ICommand = _RedoList.removeItemAt(_RedoList.length - 1) as ICommand;
command.Execute();
_UndoList.addItem(command);
}
public function Undo():void
{
if (!CanUndo)
return;
var command:ICommand = _UndoList.removeItemAt(_UndoList.length - 1) as ICommand;
command.UnExecute();
_RedoList.addItem(command);
}
//======================命令调用=============================
private function ExecuteCommand(command:ICommand):void
{
command.Execute();
AppendCommand(command);
}
private function AppendCommand(command:ICommand):void
{
//有新命令添加时清空RedoList,
DisposeUtil.Dispose(_RedoList);
_UndoList.addItem(command);
}
//======================添加、删除、编辑命令=============================
public function Add(parent:UIComponent, target:UIComponent):void
{
var command:ICommand = new AddCommand(parent, target);
ExecuteCommand(command);
}
public function Delete(parent:UIComponent, target:UIComponent):void
{
var command:ICommand = new DeleteCommand(parent, target);
ExecuteCommand(command);
}
public function Edit(property:String, target:Object, oldValue:Object, newValue:Object):void
{
var command:ICommand = new EditCommand(property, target, oldValue, newValue);
ExecuteCommand(command);
}
}
}
进阶
一个命令管理的框架基本完成了,根据实际使用,再进行扩展。
复合命令
有时,一个操作就调用了多个命令,例如,同时删除多个元件,同时移动多个元件。这需要多个命令进行复合,可以定义一个MultiCommand命令来完成多个命令同时调用。
package cwn.wb.ui.core.command
{
import cwn.core.DisposeUtil;
import mx.collections.ArrayCollection;
public class MultiCommand extends CommandBase
{
private var _Commands:ArrayCollection;
public function MultiCommand(commands:ArrayCollection)
{
_Commands = commands;
if (_Commands.length > 0)
_Title = ICommand(_Commands[0]).Title + "...";
}
override public function Execute():void
{
for each (var cmd:ICommand in _Commands)
{
cmd.Execute();
}
}
override public function UnExecute():void
{
for each (var cmd:ICommand in _Commands)
{
cmd.UnExecute();
}
}
override protected function Disposing():void
{
cwn.core.DisposeUtil.Dispose(_Commands);
super.Disposing();
}
}
}
事件通知
CommandManager是继承事件派发类EventDispatcher的,当有新的命令执行时还应该派发相应的事件,通知界面等进行刷新,数据同步。
相关资料