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的数据-实体应用程序.我们会该程序划分成若干小块,每次介绍一个部分,以便你能 ...
随机推荐
- 报错消息写在AT SELECTION-SCREEN OUTPUT和START-OF-SELECTION事件下的区别
今天面试没答上来的问题,其实我是知道的,以前也遇到过.... START-OF-SELECTION下的话会在左下角报错 AT SELECTION-SCREEN OUTPUT消息会弹出框,然后点击就没有 ...
- Python 学习入门(21)—— 线程
本文介绍了Python对于线程的支持,包括“学会”多线程编程需要掌握的基础以及Python两个线程标准库的完整介绍及使用示例. 1. 线程基础 1.1. 线程状态 线程有5种状态,状态转换的过程如下图 ...
- 基于visual Studio2013解决面试题之0309左移递减序列搜索
题目
- jquery prop和attr的区别
jquery1.6中新加了一个方法prop(),一直没用过它,官方解释只有一句话:获取在匹配的元素集中的第一个元素的属性值. 大家都知道有的浏览器只要写disabled,checked就可以了,而有的 ...
- 汉字转拼音再转ASCII
汉字能够转成拼音.能够在转成ASCII码,然后就能够转成十六进制数,再就能够转成0和1组成的二进制帧了! 比方说: 我爱你 -> wo ai ni -> 119 111 32 97 105 ...
- Android菜鸟的成长笔记(4)——你真的理解了吗?
原文:Android菜鸟的成长笔记(4)--你真的理解了吗? 在上一篇中我们查看了QQ的apk源文件中的布局结构,并仿照QQ完成了我们第一个应用的界面,详细请看<Android菜鸟的成长笔记&g ...
- java中subString、split、stringTokenizer三种截取字符串方法的性能比较(转)
最近在阅读java.lang下的源码,读到String时,突然想起面试的时候曾经被人问过:都知道在大数据量情况下,使用String的split截取字符串效率很低,有想过用其他的方法替代吗?用什么替代? ...
- STL之涉及到的算法
一.非变异算法 是一组不破坏操作数据的模板函数,用来对序列数据进行逐个处理.元素查找.子序列搜索.统计和匹配.非变异算法具有极为广泛的适用性,基本上可应用与各种容器. 1查找容器元素find 它用于查 ...
- 一个跨平台的 C++ 内存泄漏检测器
2004 年 3 月 01 日 内存泄漏对于C/C++程序员来说也可以算作是个永恒的话题了吧.在Windows下,MFC的一个很有用的功能就是能在程序运行结束时报告是否发生了内存泄漏.在Linux下, ...
- CentOS下yum使用代理的设置
export后好像没用? 问题描述: CentOS yum时出现“Could not retrieve mirrorlist http://mirrorlist.centos.org/?release ...