MVC设计模式
初学者接触到设计模式,往往会产生误解,觉得设计模式很深奥,非常复杂。其实大可不必被那些名词所吓倒,设计模式不是新技术,也不是新观念。我们可以把模式简单理解为是某一类问题的解决方式。而且是典型问题的解决方式,我们可以利用它的思想,举一反三,解决类似问题。
程序设计的很多思想其实来源于生活,只不过是用计算机语言来表达出来。只要理解了事物本质,就没有什么能难倒你的。
MVC(Model-View-Controller)架构是比较流行的开发模式,很多程序语言中都有应用,同样可以用在Flex程序中。
了解MVC原理MVC模式是由三个子系统组成的,它们分别是:Model、View、Controller。Model部件,负责装载数据和数据的行为;View部件,定义用户界面;Controller组件,处理程序中的数据。把这三点组合起来,就构成了MVC组合。
Model是在MVC组合中用于存储数据的要素,它可以存储很简单的数据,也可以存储极端复杂的数据。对于Model的定义,比较通用的说法是:它扮演数据库的角色,并且不依赖View和Controller而存在。Model与View或Controller之间没有必然的联系,这是MVC模式的一大要点,正是因为Model的独立性导致了MVC组件的巨大弹性。如果一个Model与一个View或Controller有某种对应关系,那它就被紧紧地绑定了,就只对某种特殊类型的Controller或View生效,但是,当一个Model与某种特殊类型的Controller或View没有对应关系时,它就能被用于各种类型的Controller和View之间的交流了。
View是程序的界面显示部分。Vew把Model里的数据呈现出来。一个View也就是Flex中的一个可视化组件,可能是一个List控件、一个DataGrid控件,也可能是一个Panel面板,里面包括了按钮、输入新的表单,或其他任何种类的组件,所有这些可视化的界面部分都被归于View部件中。
在View中,有部分控件用来显示数据,都是通过读取model数据来完成的。
Controller是负责处理用户的动作(例如,输入文本、点击按钮),必要时更新Model和View系统。比如,用户点击按钮,向数据端发送请求,重新加载数据,当数据加载结束,Model需要更新数据。这些都由Controller来完成。
在MVC组合中,每个部件与其他部件都保持着一种特定的关系,如图13.2所示。

图13.2
Model部件必须始终保持独立。这意味着Model不可能了解任何其他要素,也不需要了解其他要素。但这并不意味着Model与其他要素毫无联系。当Model中的数据改变时Model能通报消息,但重要的是,Model仅仅只是通报消息,而不负责谁获取消息。这种功能使Model与其他子系统的联系减弱,从而保证了其更大的弹性。
View需要单方面了解Model,见图13.2中View和Model之间的虚线,它们之间的联系是单方面的,没有约束关系。View通过两种途径与Model相互影响:它监听Model的更新消息。View和Model之间从来不进行信息交流,它只是使用Model的数据。每个View都与它相应的Model保持一种联系。Model从来不知道谁在使用自己的数据,它的数据可能被许多个View使用。
和View不同,Controller需要控制Model。Controller处理用户的交互,捕捉特定的事件,更新Model中的数据。Controller也与View紧密地联系在一起。虽然一个Controller可能对应多个View,但更普遍的情况是一个Controller对应一个View。
MVC模式的关键点在于Model的独立性,它与View或Controller之间没有对应关系。
单例模式在MVC中,Model是最重要的部件,正是由于Model的独立,才使得界面和数据处理分离开。如何才能让Model和View保持独立,每个View却可以使用同一个Model中的数据?这是整个MVC的基础。要做到这一点,需要运用单例(Singleton)模式,让Model在全局保持唯一性。当View使用的是同一个Model中的数据时,就实现了数据的同步。当Model数据变更时,所有监听Model的View更新数据时,依然能够同步更新。
单例模式,顾名思义,保持实例唯一,限制一个类只能有一个实例。通常我们要创建一个类的实例时,是通过构造函数完成的,比如:var myList:List = new List();这句代码创建了一个List控件的实例。使用构造函数,可以创建多个实例。为了要实例只有一个,需要借助类的成员变量。请看下面的例子。
文件:tree/ singleTon.as
package tree{
public class singleTon {
//定义了一个静态变量
private static var_instance: singleTon;
//公共属性,用来测试的数据
public var data:String = "Singleton Example";
//核心方法,用来访问实例
public static function getInstance():singleTon{
//如果instance还没有被实例化,则调用构造函数,这个动作只执行一次
if(_instance == null){
_instance = new ModelLocator();
}
//总是返回同一个实例对象
return _instance;
}
//构造函数,初始化数据
public function singleTon(){
data = "Singleton Example";
}
}
}
在这个类中,定义了一个静态方法getInstance和一个静态变量instance。instance就是唯一的实例对象,在程序中要访问这个对象,都必须通过getInstance方法,而不是通过构造函数。当第一次调用getInstance方法时,会调用一次构造函数,创建实例,以后就直接返回实例,从而实现了实例的唯一性。
比如我们在程序中要访问对象的data属性,可以参照下面的代码:
<mx:Script>
<![CDATA[
import model. singleTon;
internal function initApp():void{
//获得实例
var instance: singleTon= singleTon.getInstance();
//访问实例属性
trace(instance.data)
}
]]>
</mx:Script>
在MXML文件中,使用singleTon.getInstance()获得实例对象。不管这段代码写在哪一个组件中,都会得到同一个singleTon实例。
这个例子的源代码在程序SingletonExample中。
单例模式使得数据和界面组件分离,实现了数据的全局共享,是设计模式中的经典之一。
MVC和FlexFlex和MVC可谓是天生的一对,为什么这么讲?
首先,Flex采用了基于组件的开发模式,程序中的所有块都可以定义为组件。利用组件,我们将界面切分开来,同时也把功能分散到每个组件中,实现了代码的封装。
其次是Flex的事件机制,正是MVC所倡导的处理方式。当我们将界面切分后,如果要实现界面中各个部分的数据通信,必然要借助第三方。如果是直接在组件中互相传递数据,必然增加了程序的耦合度,整个结构也变得混乱。利用事件机制来处理组件之间的对话,就要清楚得多。比如Model中的数据更新时,和它有联系的View元素也要更新数据。利用事件机制,每个View元素都注册Model的监听器,设置好对应的处理方法,完全不用理会其他组件的行为。
另外,Flex的数据绑定功能为界面共享数据提供了方便,也可以发挥巨大作用。我们直接把Model中的数据作为View层的数据源,更加省心省事。
还有,利用Remoting技术,Flex可以很方便地操作后台程序,管理数据库。把Remoting接口放在Controller中,集成数据通信功能,一个完整的程序框架就实现了。
在这个框架中,Model依然处于重要地位,它负责储存数据,并传递数据更新的消息。总结起来,它具有三个特点:
1.存储数据
2.支持数据绑定
3.可以派发事件
理清了头绪后,下面就来看一个Model的实例代码。
文件:model/ ModelLocator
package model{
import flash.events.EventDispatcher;
//设置类的绑定
[Bindable]
public class ModelLocator extends EventDispatcher{
//实例
private static var _instance:ModelLocator;
//公有的静态属性
public static var username:String;
public static var password:String;
//获得实例的静态方法
public static function getInstance():ModelLocator{
if(_instance == null){
_instance = new ModelLocator();
}
return _instance;
}
}
}
ModelLocator是MVC中Model对象的惯用名。
ModelLocator对象扩展了EventDispatcher对象,不费半点力气,就拥有了派发事件和侦听事件的能力。这一点上足以体现面向对象开发的优越性。而数据绑定的实现也很简单,在类的声明前面加上[Bindable]标签就可以了。
然后,在组件中可以这样使用:
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import model.ModelLocator;
//设置对象绑定
[Bindable]
public var instance:ModelLocator = ModelLocator.getInstance();
]]>
</mx:Script>
<mx:Label x="64" y="28" text="{instance.username}" />
</mx:Panel>
注意,这里必须在instance变量的前面加上[Bindable]标签,对ModelLocator的实例设置绑定。当在程序的其他位置调用ModelLocator 对象,改变username属性的值时,上面组件中的标签控件的文本会自动更改。
……………….
<mx:Script>
<![CDATA[
import model.ModelLocator;
private var instance:ModelLocator = ModelLocator.getInstance();
internal function doChange():void{
instance.username = "My name";
}
]]>
</mx:Script>
…………………
以上例子的源代码在程序ModelExample中。
除了数据共享,利用Model还可以发送消息,也就是传递事件,详细的应用请看下一节的内容。
posted on 2013-06-20 09:55 jinglikeblue 阅读(1093) 评论(0) 收藏 举报
浙公网安备 33010602011771号