`

PureMVC学习笔记二:用FlashDevelop架设简单的MVC机制

阅读更多

 

PureMVC提供24个类(和接口),极大地简化了MVC机制的代码量。

很多类如Facade,SimpleCommand都是现成的,可以不继承就直接使用。

作为模型的Proxy可以不用。

最麻烦的是定制作为视图的Mediator类,但只需覆盖

override public function listNotificationInterests():Array 

override public function handleNotification(n:INotification):void 

这两个方法即可接收命令。

另外,PureMVC允许在Command类和Mediator类中拦截命令。

也就是说,PureMVC既可以实现发布-订阅模式(解耦接收方和发送方),

也可以实现前端控制器模式(对所有通知进行过滤和拦截,然后再转发)

 

用FlashDevelop可以这样操作(仅供参考):

(注:由于下面使用了trace函数,需要debug版的flash player独立程序或浏览器插件。

see

http://www.adobe.com/support/flashplayer/downloads.html

 

1. 下载AS3标准版swc文件

http://trac.puremvc.org/PureMVC_AS3/wiki/Downloads

 

2. 用FD创建一个ActionScript3 Flex 4 Project工程testmvc,

右键->Edit->Delete删除src下的Main.mxml。

 

3. 把swc文件复制到工程树的lib目录下,

然后右键->Add To Library添加到classpath中

 

4. src上右键->Add->New Class...添加一个类。

Name填Main,Base Class->Browse填Sprite(自动寻找)

 

5. 用类似的方法创建四个类,自动生成代码的头部是:

public class MyFacade extends Facade implements IFacade

public class MyCommand extends SimpleCommand implements ICommand

public class MyProxy extends Proxy implements IProxy

public class MyMediator extends Mediator implements IMediator

如果不记得,可以展开swc文件,查看里面带I开头的接口类。

不含IModel, IView和IControl,因为它们已经在Facade里面。

还有一种办法,就是展开swc文件,双击org.puremvc.as3.interfaces.IFacade,

查看IFacade中带register开头的函数:

public function registerCommand (param0:String, param1:Class) : void;

public function registerMediator (param0:IMediator) : void;

public function registerProxy (param0:IProxy) : void;

 

6. 为了编译,先在Main类中创建PureMVC核心。

方便起见,让它可以用文档类名直接访问。

 

public class Main extends Sprite
{
	public static var fac:MyFacade = new MyFacade();
	
	public function Main() 
	{
		
	}
}

 

然后选中Main.as右键->Always Compile。

当Main.as变成绿色后,按工具栏上的编译按钮。

 

7. 到此为止除FD自动生成的内容外,

只写了一句代码,所以很容易就编译通过。

展开生成的bin/testmvc.swf,发现里面除了puremvc的类外,

只有Main和MyFacade两个类。

需要进一步编译其它类。

 

8. 打开MyFacade.as,在构造函数中创建和注册其余的所有类,

然后创建相应的命令常量:

 

 

public class MyFacade extends Facade implements IFacade
{
	public static const MY_COMMAND:String = "mycommand";
	
	public function MyFacade() 
	{
		this.registerCommand(MY_COMMAND, MyCommand);
		this.registerMediator(new MyMediator());
		this.registerProxy(new MyProxy());
	}
}

 

 

为什么命令类的注册方式与众不同呢?

那是因为命令类实例通常由PureMVC的机制自动生成,而不是由程序员手工创建

 

9. 按工具栏上的编译按钮,编译通过

注意导入Proxy类是import org.puremvc.as3.patterns.proxy.Proxy。

如果导入的是flash.utils.Proxy,编译会出错。

 

10. 现在,可以在任何地方发送命令给facade,

然后让facade把这个命令发给中介类MyMediator。

中介的意思是,它的方法不允许直接被外部的类调用(虽然它有public方法):

 

11. 在点击舞台时发送命令MY_COMMAND(它已经被注册绑定到MyCommand),

附带一个字符串"onClick"(它的引用被一起发到接收方)

 

 

public class Main extends Sprite
{
	public static var fac:MyFacade = new MyFacade();
	
	public function Main() 
	{
		this.stage.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
	}
	
	private function onClick(e:MouseEvent):void 
	{
		Main.fac.sendNotification(MyFacade.MY_COMMAND, "onClick");
	}
}

 

 

12. 然后想办法拦截这个MyFacade.MY_COMMAND命令。

方法是,覆盖中介类的listNotificationInterests和handleNotification方法。

注意:

(1) 需要导入INotification接口。

(2) getName是方法,不是属性,需要加括号

(3) 如果listNotificationInterests方法没有覆盖,handleNotification将无效

 

 

package  
{
	import org.puremvc.as3.interfaces.IMediator;
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	import org.puremvc.as3.interfaces.INotification;
	
	/**
	 * ...
	 * @author 
	 */
	public class MyMediator extends Mediator implements IMediator
	{
		public function MyMediator() 
		{
			
		}
		
        override public function listNotificationInterests():Array 
        {
            return [MyFacade.MY_COMMAND];
        }
		
        override public function handleNotification(n:INotification):void 
        {
            switch (n.getName()) 
			{
				case MyFacade.MY_COMMAND:
					trace(n.getBody() as String);
					break;
            }
        }
	}
}

 

 

编译后运行,发现每当鼠标点击舞台,都会产生内容为onClick的调试输出。

 

13. 另一种拦截方法是覆盖命令类的execute方法:

 

 

package  
{
	import org.puremvc.as3.interfaces.ICommand;
	import org.puremvc.as3.patterns.command.SimpleCommand;
	
	import org.puremvc.as3.interfaces.INotification;
	
	/**
	 * ...
	 * @author 
	 */
	public class MyCommand extends SimpleCommand implements ICommand
	{
		
		public function MyCommand() 
		{
			
		}
		
		override public function execute(n:INotification):void    
		{
			trace("execute:" + n.getBody() as String);
		}
	}
}

 

 

它不需要switch,也比handleNotification先执行。

 

14. 现在已经体验了四个类的作用:

Main对象用于界面和实例创建

MyFacade对象用于注册实例,定义命令常量和发送命令。

MyCommand类用于命令发送时的拦截(用于无目标视图的通知)。

MyMediator类用于命令接收时的拦截(用于有目标视图的通知)。

 

15. 代理类对象的生命周期比命令类长。

通常用于存储网络接收的数据。

也可用于在中介之间共享状态(在通知发送之前修改),

这样一来就能避免使用单实例模式。

在基类的构造函数中指定名称和绑定数据的初始值。

 

 

package
{
	//import flash.utils.Proxy
	import org.puremvc.as3.patterns.proxy.Proxy;
	import org.puremvc.as3.interfaces.IProxy;
	
	/**
	 * ...
	 * @author 
	 */
	public class MyProxy extends Proxy implements IProxy
	{
		public function MyProxy() 
		{
			super("myproxy", 0);
		}
	}
}

 

 

然后在命令发送前改变它(通过名称取出引用)。

 

 

 

package  
{
	import org.puremvc.as3.interfaces.ICommand;
	import org.puremvc.as3.interfaces.IProxy;
	import org.puremvc.as3.patterns.command.SimpleCommand;
	
	import org.puremvc.as3.interfaces.INotification;
	
	/**
	 * ...
	 * @author 
	 */
	public class MyCommand extends SimpleCommand implements ICommand
	{
		
		public function MyCommand() 
		{
			
		}
		
		override public function execute(n:INotification):void    
		{
			var proxy:IProxy = this.facade.retrieveProxy("myproxy");
			proxy.setData(proxy.getData() + 1);
			trace("execute:" + n.getBody() as String);
		}
	}
}

 

然后在命令接收后读出来:

 

 

package  
{
	import org.puremvc.as3.interfaces.IMediator;
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	import org.puremvc.as3.interfaces.INotification;
	
	/**
	 * ...
	 * @author 
	 */
	public class MyMediator extends Mediator implements IMediator
	{
		public function MyMediator() 
		{
			
		}
		
        override public function listNotificationInterests():Array 
        {
            return [MyFacade.MY_COMMAND];
        }
		
        override public function handleNotification(n:INotification):void 
        {
            switch (n.getName()) 
			{
				case MyFacade.MY_COMMAND:
					trace(n.getBody() as String);
					trace("proxy data:" + this.facade.retrieveProxy("myproxy").getData());
					break;
            }
        }
	}
}

 

 

因为getData()和setData()的代码灵活性不够高,

可以在MyProxy中定义新的属性,

再用类似的方法保存状态。

 
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics