摘要: 本文首先介绍了标准的 MVC 体系构架,同时也介绍了最常见的一类 MVC 模式的变种。之后,文章重点介绍了 MVC 结构在 gef 框架中的体现与应用,以及 gef 是如何综合利用工厂模式、命令模式等设计模式来辅助 MVC 结构的实现。例如 gef 成功利用命令模式分担了控制器的部分责任。

前言

GEF 全称 Graphical Editor Framework 。它是一个基于 eclipse 的图形化编辑框架。通过它,开发人员可以方便的以图形化的方式(而非文本的方式)展示和编辑模型。 GEF 是一种很有价值的工具,很多著名的应用都采用了 gef 框架,其中包括现在最流行 的开源工作流 jbpm 的定制工具。 Gef 是按照标准的 mvc 模式实现的,其中还使用到了工厂模式、命令模式, Policy 模式等一些设计模式。

MVC 结构

MVC 是 "Model-View-Controller" 的缩写,即 ” 模式 - 视图 - 控制器 " 。 MVC 结构强制将一个 应用分为模型层、视图层以及控制器。通过三者之间的协调共同响应完成用户的请求,即交互过程。

它们之间的协作关系如图:

上图为 mvc 模式最标准也是最常见的一种形态。从上图可以看出,模型与视图不直接打交道,而是通过控制器,即控制器完全分离了视图与模型。这是 mvc 模式的最大特点之一。

在现实开发中,由于实际需要,开发设计人员通常会对标准的 mvc 模式进行一些修改。屏弃其中的某些特性,而加入新的特性。其中最常见的变化形式如下图所示:

可以看到,控制器并没有完全分离视图与模型。即它不再负责根据模型修改视图,这一过程是让模型与视图双方“面对面”直接进行。这样做虽然增强了视图与模型之间的耦合,但是减轻了控制器的负担。

另外,在通常情况下,为了进一步解耦合,层与层之间的数据通过一种叫做 DTO 即数据传输对象的介质进行传递。 DTO 的时间通常很简单,只有若干属性和属性对应的 get/set 方法,是一个标准的纯 java 对象,即 pojo 。例如基于 mvc 结构的 struts中的 actionFrom 即为一个 DTO 。

视图

视图层的作用主要有两个:

l  接收用户输入,将输入信息传递给控制层。

l  负责展示数据,它将模型层中的具体数据以一定的形式展示给用户。

模型和视图之间是一个多对多的关系,一个模型可以对应多个视图,一个视图也可以关联多个模型。

控制器

控制层接收到视图层传递过来的请求后,分析请求信息,根据请求内容选择相应的模型,并修改模型的具体数值。

同时当模型发生变化的时候,将会通知控制器,以更新视图。

模型

模型是行为与状态的双重抽象,即封装了数据与方法。当模型发生变化时,相应的视图会根据新的模型数据重新绘制展现内容。

优点

使用 mvc 结构的应用有如下有点:

l  便于分工。 Mvc 机构将程序分为 ’M - V - C’ 三层,这三层各司其职。这样便于分工协作。例如,传统结构的应用将业务逻辑和界面显示混杂在一起,这样美工很难对页面进行美化。而 mvc 结构的应用,将应用分层,视图层只有展现代码便于美工美化页面。

l  提高了代码的可重用性。多个视图能共享一个模型,多个模型也能共享一个视图,提高了代码的可重用性。

l  便于维护更新,由于 mvc 的解耦合特性。使得维护和变更相对变得比较容易。因此可以方便地改变应用程序的业务数据和业务规则,迁移数据库等等。 不会牵一发而动全身。

Gef 中的 mvc 实现

Gef 完全按照标准的 mvc 体系结构完成。

模型

Gef 模型的规约十分宽泛——任何 java 类都可以作为 gef 的模型。也就是说, gef 在模型层是非侵入式的。这一点使得 gef的应用更加广泛,灵活。

但是为了能够让控制器知道模型的变化,我们需要一种机制——让模型发生变化的时候通知控制器。由于灵活性的需要,gef 并没有把这种机制实现在框架层。但是我们通常会在模型层中添加 PropertyChangeSupport 类型的成员变量,用来触发事件,通知控制器。例如:

public class AbstractModel {

private PropertyChangeSupport listeners = new PropertyChangeSupport(this);

public void addPropertyChangeListener(PropertyChangeListener listener) {

listeners.addPropertyChangeListener(listener);

}

public void firePropertyChange(String propName, Object oldVal, Object newVal) {

listeners.firePropertyChange(propName, oldVal, newVal);

}

public void removePropertyChangeListener(PropertyChangeListener listener) {

listeners.removePropertyChangeListener(listener);

}

}

视图

视图是模型图形方式的表现,它以某种方式展示模型。 Gef 是一个图形编辑框架,所以 gef 的视图主要是将模型以图形化的方式显示出来。虽然任何实现 IFigure 接口的类都可以作为视图,但是 GEF 使用 Draw2D 可视图形( figure )。 Draw2d 是 SWT 平台上的图形库,你可以用它定制属于自己的、不依赖于特定操作系统本地组件的上层组件。

那么视图又是如何显示的呢。这要用到 AbstractEditPartViewer ,它负责将视图安装到同一个 SWT Control 上。

控制器

在 gef 中,控制器又称为编辑部件 , 是模型和视图之间的桥梁,也是 gef 最重要的部分。所有的 Gef 控制器都需要继承 EditPart 类。

      根据 mvc 体系结构,控制器的功能主要有两个。

l  监听模型的变化,根据变化修改视图。

l  当用户编辑视图时,把编辑的结果反映到对应得模型中。

创建——工厂模式

Gef 在控制器的生成中,使用了工厂模式。 通常每一个模型都对应一个控制器,所以 gef 要求提供一个 EditPartFactory ,该对象负责通过给定的模型创建与之对应的控制器。

当模型被创建的时候, EditPartFactory 将会被调用,创建出模型对应的控制器。

监听模型变化

控制器需要监听模型的变化,从而根据新的模型数据重新显示视图。那么就需要将控制器注册成为模型的监听者。例如下面的代码

public void activate() {

if (isActive()) {

return;

}

super.activate();

((Node) getModel()).addPropertyChangeListener(this);

}

public void deactivate() {

if (!isActive()) {

return;

}

super.deactivate();

((Node) getModel()).removePropertyChangeListener(this);

}

方法 activate 的作用是当被激活的时候,把自己注册成为模型的监听。 Deactivate 相反,当失活的时候,将自己从对应的模型的监听者中删除。

由于模型层使用了 PropertyChangeSupport 类,所以,控制器需要 实现 PropertyChangeListener 接口。PropertyChangeListener 要求实现 propertyChange 方法。

public interface PropertyChangeListener extends java.util.EventListener {

void propertyChange(PropertyChangeEvent evt);

}

当模型发生变化时,对应控制器的 propertyChange 方法将会被调用。要说明的是,在 gef 应用中,控制器通常负责根据模型数据修改视图显示,而非简单的通知视图重画。

修改模型——策略与命令

当用户进行编辑操作的时候,控制器还需要解析这些操作并修改相应的模型。这通常是一系列负责的操作,可能会使得控制器非常庞大。 Gef 通过进入请求编辑策略与命令模式很好大分担了控制器的本身的负担。也达到了解耦合的目的。其中编辑策略用于解析用户编辑请求,命令用于修改模型。

同时引入命令模式的另外一个目的就是“回退”功能,一个好的图形编辑器“回退”功能是必不可少的。命令模式通过“ redo ”和“undo ”等操作可以很多好的支持“重做”以及“回退”的功能。

当控制器接收到用户的编辑请求后,会根据请求对象中的角色信息寻找处理该请求的编辑策略。要说明的是,编辑策略需要事先被注册安装到控制器中,并对应相应的角色。角色是 gef 框架抽象出来的一个标识。控制器 EditPart 就是通过角色标识找到处理请求的策略的。

编辑策略接收到请求后,分析请求信息。根据分析的结果选择创建相应的命令,并且初始化命令的相关参数。

由 gef 框架负责执行编辑策略产生的命令。命令将会修改相应的模型。同时 gef 框架会记录下执行的命令,以备“重做”“后退”等功能使用。

用户编辑请求响应过程

综上所述,在 gef 框架中,用户编辑请求的相应过程如下:

1.        当用户进行编辑操作时, gef 框架将操作封装成一个请求对象,并将其传递给控制器。

2.        控制器根据角色选择相应的编辑策略处理请求。

3.        编辑策略分析请求数据,创建并初始化命令对象。

4.        命令执行的过程就是修改模型的过程。

5.        当模型被修改后,将会触发事件,告知其监听者——该模型对应的控制器。

6.        控制器根据模型数据修改视图显示。

结束语

Gef 是一个完全基于 MVC 体系构架搭建的图形编辑框架。正是 MVC 体系构架的进入,使得模型层与视图层解耦合。那么模型层的约束就得到了极大的解放。这意味着 gef 可以适用于更广泛的业务。也正是 MVC 体系结构的进入,使得基于 gef 框架开发的应用结构更加清晰,更加有利于分工开发与后期维护。

同时 gef 引入了请求编辑策略与命令模式成功分解了 gef 控制层的负担。其中命令模式的引入也使得应用支持“重做”“回退”等功能。

转自:http://www.iteye.com/topic/788210

GEF的MVC体系结构的更多相关文章

  1. Spring MVC体系结构和处理请求控制器

    Spring MVC体系结构和处理请求控制器 一:MVC设计模式: (1.)数据访问接口:DAO层 (2.)处理业务逻辑层:Service层 (3.)数据实体:POJO (4.)负责前段请求接受并处理 ...

  2. Spring MVC体系结构

    [Spring MVC类图]<Spring实战>中:<Spring3.0就这么简单>中:[http://blog.csdn.net/gstormspire/article/de ...

  3. spring MVC体系结构和请求控制器

    MVC处理过程 spring MVC架构模式都进行了分层设计如下 数据访问接口:DAO层 处理业务逻辑层:service层 数据实体:POJO 负责前端请求的接受并处理:servlet 负责前端页面展 ...

  4. Spring MVC 相关资料整理

    来源于:http://www.cnblogs.com/ylhssn/p/4062757.html 1.概述 Spring MVC是一种基于Java实现MVC设计模式的请求驱动类型的轻量级Web框架,即 ...

  5. ASP.NET MVC掉过的坑_MVC初识及MVC应用程序结构

    APS.Net MVC 浅谈[转] 来自MSDN 点击访问 MVC 理论结构 模型-视图-控制器 (MVC) 体系结构模式将应用程序分成三个主要组件:模型.视图和控制器. ASP.NET MVC 框架 ...

  6. Spring MVC 学习笔记(整理)

    SpringMVC学习 1.概述 Spring MVC是一种基于Java实现MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行解耦,基于请求-响应模型帮助我们 ...

  7. ASP.NET MVC Overview

    ASP.NET MVC Overview The Model-View-Controller (MVC) architectural pattern separates an application  ...

  8. .net mvc笔记1_ The MVC Pattern

    1.controller中的每一个public method被称为action method,意味着你可以从web上通过URL来调用它,以此来执行一个action. 2.当我们从action meth ...

  9. Pro ASP.NET MVC –第二章 第一个MVC程序

    学习一个软件开发框架的最有效的方式就是了解并使用它.在本章,你将会创建一个简单基于ASP.NET MVC Framework的数据-实体应用程序.我们会该程序划分成若干小块,每次介绍一个部分,以便你能 ...

随机推荐

  1. MySqlClient访问tinyint字段返回布尔值

    原文 MySqlClient访问tinyint字段返回布尔值 症状: 使用MySqlClient访问tinyint       unsign 字段返回布尔值 true 和        false,但 ...

  2. iPhone App开发实战手册学习笔记(9)之设计IOS App的目标

    1 前言 如果我们要做一个属于自己的App需要达到那些目标呢,今天就来介绍一下. 2 详述 2.1 关注用户及其需求 你的主要目标永远都是在设计方案之前先想好用户用例.有些开发人员喜欢编写用户故事来确 ...

  3. gridView自己定义做时间排版

    公司有需求要做一个时间排版,原型例如以下 由于要用的gridView,曾经就是它的排版非常多,最看是想用一个checkbox搞定. 后来证实功能可以达到.可是排版是乱的.还是老老实实多写点吧(直接上代 ...

  4. Android事件详解——拖放事件DragEvent

    1.Android拖放框架的作用? 利用Android的拖放框架,可以让用户用拖放手势把一个View中的数据移到当前layout内的另一个View中去. 2.拖放框架的内容? 1)拖放事件类 2)拖放 ...

  5. 轻量级工具网站SimpleTools

    [解释]本来这篇文章是在前天发出来的,可是当时是刚申请的域名,现在都要域名实名认证,导致我发的项目网址打不开,惹来了很多博友的吐槽,在此说声抱歉,今天一大早就把实名认证提交了,现在网站已经可以正常访问 ...

  6. ecshop 微信支付插件

    眼下已完毕支付測试,可以支付成功,支付逻辑自己实现.后台通知.发货通知.订单查询未測. 当中用到了redis 下载

  7. 按 Eclipse 开发喜好重新布置 cocos2dx 目录层次

    [tonyfield 2013.08.29 ] 1.  Cocos2dx 库的改动 处于个人的固执,花一天时间重新布置了cocos2dx 2.1.4的目录层次,将android平台无关的代码全数裁剪, ...

  8. html中加入超链接方式的汇总

    在CSS样式中,对超链接的样式有以下几种定义(1)设置链接未被访问时的样式,具体写法如下:a:link{font-size:10px;... }(2)设置链接在鼠标经过时的样式,具体写法如下:a:ho ...

  9. 对TMemoryStream的一些改进(用到了LockFile)

    对TMemoryStream的一些改进 怎么又是关于Stream的,呵呵,应该说只是最近比较关心程序的效率问题,而我对Stream其实并没有什么特别的研究,只是自己发现了一些新的用法,希望能对大家有用 ...

  10. ThinkPhp学习11

    原文:ThinkPhp学习11 一.模板的使用        (重点) a.规则 模板文件夹下[TPL]/[分组文件夹/][模板主题文件夹/]和模块名同名的文件夹[Index]/和方法名同名的文件[i ...