MVC设计模式

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所示。

MVC设计模式 - jinglikeblue - jinglikeblue 的博客

图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和Flex

Flex和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)    收藏  举报

导航