puremvc是一个可应用于多种语言、多种平台的mvc框架。根据官网上的描述,现在已经支持下列语言:
官方也推出了最佳实践的中文文档,当然,园子里也有兄弟说它烂的 :)
跟asp.net mvc框架有所不同,在asp.net mvc中,一个http请求过来,controller会自动去取得数据,最终转化为model,然后选取一个view进行呈现,同时把model传到view中,一切还算比较简单。
然而puremvc除mvc模式外,渗杂了更多的模式:比如facade(门面),observer(观察者),singleton(单件)等等
先不管其它,来一个flex版本的Hello World吧。(注:以下内容参考了Pure MVC第一步:最简PureMVC)
整个项目结构:
这个项目最终就是要在界面上显示一个文本框,一个按钮,点击按钮时,文本框内容发生改变。(注:该项目纯粹是为了puremvc而puremvc,不具实践意义,仅仅只是出于学习目的,刻意简化的一个示例) 另:因为这个项目不涉及具体的数据实体类,所以model这部分就省去了。
在puremvc中,model/view/controller统一是由Facade类的单件实例来统筹管理的。
大致流程可理解为:通过Facade类的单件实例(即:统一的门面) 启动 puremvc环境,启动同时注册Command对象(相当于asp.net mvc中的controller),然后Command通过与之关联的facade(即前面的单件实例)来注册Mediator(中介者:用于把View与Command联系起来)。
当UI界面(即View)上有动静时(比如按钮点击了之类),与之关联的Mediator(中介者)会发送通知给facade,然后facade会调用command对象执行相关的处理。(即:消息响应)
应该不难理解吧:
1、先在flash builder中创建一个flex项目,同时添加puremvc相关的swc引用,然后主界面main.mxml内容如下:
1
2
3
4
5
6
7
8
9
10
11
|
<?xml version=
"1.0"
encoding=
"utf-8"
?>
<s:Application xmlns:fx=
"http://ns.adobe.com/mxml/2009"
xmlns:s=
"library://ns.adobe.com/flex/spark"
xmlns:mx=
"library://ns.adobe.com/flex/mx"
minWidth=
"300"
minHeight=
"200"
height=
"42"
width=
"300"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:TextInput x=
"10"
y=
"10"
width=
"206"
id=
"txtResult"
/>
<s:Button x=
"224"
y=
"9"
label
=
"Button"
id=
"btnSend"
/>
</s:Application>
|
2、创建门面AppFacade类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
package
mvc
{
import
mvc.controller.AppCommand;
import
org.puremvc.as3.interfaces.IFacade;
import
org.puremvc.as3.patterns.facade.Facade;
public
class
AppFacade
extends
Facade
implements
IFacade
{
public
static
const
START_UP:
String
=
"start_up"
;
public
static
const
CHANGE_TEXT:
String
=
"change_text"
;
public
function
AppFacade()
{
}
public
static
function
getInstance():AppFacade
{
if
(instance ==
null
)
{
instance=
new
AppFacade();
}
return
instance
as
AppFacade;
}
protected
override
function
initializeController():
void
{
super
.initializeController();
this
.registerCommand(START_UP, AppCommand);
//入口:注册Command
}
//启动puremvc环境
public
function
startup(_main:main):
void
{
//注:这里的main即为UI界面main.mxml对应的类
this
.sendNotification(START_UP, _main);
//启动时,发送通知
}
}
}
|
当然,这不是一个严格意义的单件(构造函数仍然可调用,不过这里不想把代码弄得太复杂,大家暂时把它当做一个单件来看待吧) 。
注:注意这里加注释的部分,在initializeController中,注册了一个Command对象(AppCommand在代码下面会贴出),这样就把门面Facade与命令Command联系起来了,另外在startup里,把主界面main.mxml对应的类实例使用_main传递进来,这样puremvc环境就跟程序主类联系起来了。
3、创建AppCommand类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package
mvc.controller
{
import
mvc.view.ButtonMediator;
import
mvc.view.TextMediator;
import
org.puremvc.as3.interfaces.INotification;
import
org.puremvc.as3.patterns.command.SimpleCommand;
public
class
AppCommand
extends
SimpleCommand
{
public
function
AppCommand()
{
super
();
}
public
override
function
execute(inote:INotification):
void
{
var
_main:main=inote.getBody()
as
main;
//注册:中介者(用于连接view与command)
facade.registerMediator(
new
TextMediator(_main.txtResult));
facade.registerMediator(
new
ButtonMediator(_main.btnSend));
}
}
}
|
注:这里的execute方法中,通过facade引用,得到puremvc中的门面Facade唯一实例,然后注册Mediator中介者,把界面上的元素(即输入框与按钮)跟门面也关联起来了。
4、中介者(TextMediator与ButtonMediator)
这也是跟asp.net mvc不同的一个地方,puremvc并没有直接操作视图(View)上的元素,而是引入了中介者(Mediator)这个概念,它相当于“View上的具体元素”与Command之间的桥梁,这样的好处,就是进一步解耦,从一定程度上消除对具体界面的依赖。
ButtonMediator.as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package
mvc.view
{
import
spark.components.Button;
import
flash.events.MouseEvent;
import
mvc.AppFacade;
import
org.puremvc.as3.interfaces.IMediator;
import
org.puremvc.as3.patterns.mediator.Mediator;
public
class
ButtonMediator
extends
Mediator
implements
IMediator
{
public
static
const
NAME:
String
=
"ButtonMediator"
;
public
function
ButtonMediator(viewComponent:Button)
{
super
(NAME,viewComponent);
this
.btnInstance.addEventListener(MouseEvent.CLICK,btnClick);
}
private
function
btnClick(e:MouseEvent):
void
{
this
.sendNotification(AppFacade.CHANGE_TEXT,
"Hello PureMVC !"
);
}
//获取UI界面上的“按钮实例"
private
function
get
btnInstance():Button{
return
viewComponent
as
Button;
}
}
}
|
可以看到,ButtonMediator通过调用sendNotification方法向puremvc环境发送消息CHANGE_TEXT就完事了,至于谁去接收消息,它不关心。
TextMediator.as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
package
mvc.view
{
import
spark.components.TextInput;
import
mvc.AppFacade;
import
org.puremvc.as3.interfaces.IMediator;
import
org.puremvc.as3.interfaces.INotification;
import
org.puremvc.as3.patterns.mediator.Mediator;
public
class
TextMediator
extends
Mediator
implements
IMediator
{
public
static
const
NAME:
String
=
"TextMediator"
;
public
function
TextMediator(viewComponent:TextInput)
{
super
(NAME,viewComponent);
}
public
override
function
listNotificationInterests():
Array
{
return
[AppFacade.CHANGE_TEXT];
}
//响应消息
public
override
function
handleNotification(notification:INotification):
void
{
switch
(notification.getName()){
case
AppFacade.CHANGE_TEXT:
this
.txtInstance.text = notification.getBody()
as
String
;
break
;
}
}
//获取与之关联的UI界面上的“文本输入框”
private
function
get
txtInstance():TextInput{
return
viewComponent
as
TextInput;
}
}
}
|
在这段代码中,TextMediator负责监听CHANGE_TEXT消息,同时得到消息后,会做出反应。这样跟上面的ButtonMediaor一唱一合,完成了整个消息的处理。
ok,代码准备得差不多了,回过头在main.mxml中正式启用puremvc环境吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?xml version=
"1.0"
encoding=
"utf-8"
?>
<s:Application xmlns:fx=
"http://ns.adobe.com/mxml/2009"
xmlns:s=
"library://ns.adobe.com/flex/spark"
xmlns:mx=
"library://ns.adobe.com/flex/mx"
minWidth=
"300"
minHeight=
"200"
height=
"42"
width=
"300"
creationComplete=
"application1_creationCompleteHandler(event)"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import
mvc.AppFacade;
import
mx.events.FlexEvent;
protected
function
application1_creationCompleteHandler(event:FlexEvent):
void
{
//启动puremvc环境
AppFacade.getInstance().startup(
this
);
}
]]>
</fx:Script>
<s:TextInput x=
"10"
y=
"10"
width=
"206"
id=
"txtResult"
/>
<s:Button x=
"224"
y=
"9"
label
=
"Button"
id=
"btnSend"
/>
</s:Application>
|
示例源代码下载 (flash builder4环境)
最后再附上一张puremvc的结构图: