GEF的MVC体系结构
摘要: 本文首先介绍了标准的 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体系结构的更多相关文章
- Spring MVC体系结构和处理请求控制器
Spring MVC体系结构和处理请求控制器 一:MVC设计模式: (1.)数据访问接口:DAO层 (2.)处理业务逻辑层:Service层 (3.)数据实体:POJO (4.)负责前段请求接受并处理 ...
- Spring MVC体系结构
[Spring MVC类图]<Spring实战>中:<Spring3.0就这么简单>中:[http://blog.csdn.net/gstormspire/article/de ...
- spring MVC体系结构和请求控制器
MVC处理过程 spring MVC架构模式都进行了分层设计如下 数据访问接口:DAO层 处理业务逻辑层:service层 数据实体:POJO 负责前端请求的接受并处理:servlet 负责前端页面展 ...
- Spring MVC 相关资料整理
来源于:http://www.cnblogs.com/ylhssn/p/4062757.html 1.概述 Spring MVC是一种基于Java实现MVC设计模式的请求驱动类型的轻量级Web框架,即 ...
- ASP.NET MVC掉过的坑_MVC初识及MVC应用程序结构
APS.Net MVC 浅谈[转] 来自MSDN 点击访问 MVC 理论结构 模型-视图-控制器 (MVC) 体系结构模式将应用程序分成三个主要组件:模型.视图和控制器. ASP.NET MVC 框架 ...
- Spring MVC 学习笔记(整理)
SpringMVC学习 1.概述 Spring MVC是一种基于Java实现MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行解耦,基于请求-响应模型帮助我们 ...
- ASP.NET MVC Overview
ASP.NET MVC Overview The Model-View-Controller (MVC) architectural pattern separates an application ...
- .net mvc笔记1_ The MVC Pattern
1.controller中的每一个public method被称为action method,意味着你可以从web上通过URL来调用它,以此来执行一个action. 2.当我们从action meth ...
- Pro ASP.NET MVC –第二章 第一个MVC程序
学习一个软件开发框架的最有效的方式就是了解并使用它.在本章,你将会创建一个简单基于ASP.NET MVC Framework的数据-实体应用程序.我们会该程序划分成若干小块,每次介绍一个部分,以便你能 ...
随机推荐
- 在DLL动态链接库中封装VCL的MDI子窗体
在DLL动态链接库中封装VCL的MDI子窗体不多说了,看代码就应该明白了,曾经我遇到的问题,现在放出来大家共享! 这里是工程文件的部分: 在DLL中封装MDI子窗体需要重写DLL入口函数,具体代码如下 ...
- iOS国际化时遇到的错误:read failed: the data couldn't be read because it isn't in the correct format.
事实上这个错误非常easy,就是当我们在国际化的时候,写key,写着写着就忘了加 ";" 所以查看一下自己的Localization文件就能够了
- Hook任务栏时钟窗口(原理其实很简单,就是注入DLL到时钟窗口进程(explorer.exe))
用过一些日历软件的小伙伴应该都知道它们都实现了在时钟窗口上的Hook,也就是屏蔽了系统原有的功能,实现自己的功能 某日历软件Hook时钟窗口后的效果 经过一番研究,发现原理其实很简单,就是注入DLL到 ...
- 默认情况下,不使用of子句表示在select所有的数据表中加锁(转)
Select …forupdate语句是我们经常使用手工加锁语句.通常情况下,select语句是不会对数据加锁,妨碍影响其他的DML和DDL操作.同时,在多版本一致读机制的支持下,select语句也不 ...
- Swift - 使用UIWebView和UIToolbar制作一个浏览器
使用网页控件(UIWebView)与工具栏控件(UIToolbar),我们可以自制一个小型的浏览器,其功能如下: 1,输入网址,点击“Go”按钮加载网页 2,加载过程中有进度条,同时可以点击停止按钮取 ...
- 百度搜索结果页url参数详解
在百度首页输入任意关键词搜索之后,我们跳转到搜索结果页面,在浏览器的网址栏我们可以看到很长的一串url地址.那么,你真的了解这一串url的含义吗? s?:搜索 百度搜索结果页使用了重定向,因此我们看到 ...
- blender资源
blender资源 只能发帖不能更改的百度贴吧贴. http://tieba.baidu.com/f?kw=blender blendercn youku视频专辑: http://i.youku.co ...
- 【LeetCode】Min Stack 解题报告
[题目] Design a stack that supports push, pop, top, and retrieving the minimum element in constant tim ...
- VCL改变主窗体的方法
使用如下语句即可Pointer((@Application.MainForm)^) := Form1; 仔细想想和Pointer((Application.MainForm)) := Form1;有什 ...
- 菜鸟玩云计算之十一:Hadoop 手动安装指南
Hadoop 手动安装指南 cheungmine 2013-4 本文用于指导在Windows7,VMWare上安装Ubuntu, Java, Hadoop, HBase实验环境. 本指南用于实验的软件 ...