




已阅读5页,还剩29页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Easy MVC开发人员指南 翻译:丁士锋 东莞虎门镇居岐 1.Introduction 1.1 Whats Easy MVC Easy MVC or eMVC是一个轻量级MVC框架,为Delphi程序员设计来开发Windows应用程序。 1.2 为什么我们需要eMVC? Model-View-Controller(MVC)成为一个通用性和强有力的架构很多年了,Internet上有百计的MVC框架(免费的或商业的)可以使用,但他们大多数都很庞大,难于学习难以理解,特别是在软件设计方面知识和经验都有限的初学者。 另一个问题是,近来所有的MVC框架都是用JAVA,PHP而不是DELPHI写的,这是我们什么写eMVC的原因。 1.3 基于eMVC的应用程序看起来像什么? eMVC实现了 Model-View-Controller设计模式,比之其它MVC框架,eMVC引入了一个新概念:mset(mset),mset是一个能完成实际功能的模块,在程序中作为一个最小元素。 一个标准的mset包含一个控制器,一个模型和一个或多个视图,模型包含应用程序商业逻辑,视图作为接受输入或显示信息的用户界面。 框架提供了单一入口点-ControlCenter,所有的控制器必须注册到ControlCenter;ControlCenter存放所有注册的Controller到一个队列。 下图显示了一个高级别的框架概要图。 This image has been resized to fit in the page. Click to enlarge.在图1.1中可以见到,基于eMVC框架的应用程序有一个ControlCenter,ControlCenter维护着一个控制器队列,你可以添加一个或多个mSet到应用程序,我们将简短说明下mset中的每个组件的细节。 2,The Beneifts(好处) 设计模式(不光是MVC模式)现在是一个工业标准,关于这个主题有很多优秀的书和资源,以帮助开发团队加速学习过程。学习使用像eMVC这样的框架是需要一些努力的,大多数努力是值得的,无论如何作为一个认真的delphi程序员,通过使用如MVC一这些的设计模式所带来的好处,来回报你的这种努力。(大概就是这样): 1,加强模块化和应用程序分层。 2,弱代码藕合。 3,增强开发/设计角色分配,并行工作成为可能。 4,增加代码可管理性。 5,增加代码可扩展性。(有变更采纳能力) 更多有用的功能将在新版本中加入,未来将有更多好处,不要忘了最重要的事情 eMVC开源授权书让你完全的访问源代码. 3,Essentials 本质 好,在使用eMVC前,最好是有一些使用2种简单和常用的设计模式Observer(观察者)和职责链的知识与动机。著名的 Model-View controller模式也是。实际上,MVC并不属于26种设计模式。 3.1 观察者模式。 3.1.1 知识 考虑(图3.1)的案例,你有三个Windows(Observer 1,2,3),每个Window包含一个SpreadSheet,一个Bar Chart和一个Pie Graphic.都描述同一相应用程序数据对象的信息。SpreadSheet(表格),bar Chart(条形图)和Pie Graphic(饼图)之间并不相互了解。因而你能在你需要时重用他们中的任何一个。当用户在电子表格中改变了信息,条形图和饼图立即反映出这种改变。其他的也可以以此类推。 观察者模式描述如何建立这些关系,我们知道,在这个模式中的关建对象是Observable Subject和Observers. 这个模式有一些规则: a)一个obServable subject或许有多个依赖的observers. b)所有的observers必须将自己注册到observable subject。 c)只要Observable subject被变化所有的Observers都被通知。 d),在响应方面,每个Observer将查询observable subject来同步他的状态和Subject的状态。 3.1.2 eMVC中的Observer 图3.2是eMVC框架的类模型,这里有两个接口用于观察者模式。IObservable 和IObserver. IObservable 被设计用于要观察的对象(Observable object),IObserver为被观察对象。 TObservable是IObservable的默认实现.源自TInterfaceObject且实现IObservable接口。 这两个接口的原代码如下: /Observer interfaceIObserver = interface3E91264F-BBC0-44DF-8272-BD8EA9B5846C Procedure UpdateView(o: TObject);end;/Observable interfaceIObservable = interfaceA7C4D942-011B-4141-97A7-5D36C443355F procedure RegObserver(observer: IObserver); procedure Notify(o: TObject);end我们见到,这两个接口相当简单。 A:IObservable IObservable只有两个过程:RegObserver()和Notify().RegObserver()被用来注册Observers.当Observable Subject改变调用 notify()以告诉所有被观察的对象(Observers)。 B:IObServer IObServer只有一个过程UpdateView(),当Notify被调用时将被自动触发。见TObservalbe中notify()的实现。 C:TObservable TObservable是IObservable接口的默认实现,我强烈建议你从TObservable派生你的新类以取代使用IObservable接口。 在TObservable类中有一个Private域称为IObservers.以存放所有以注册的Observers. 在 Notify()过程里,一个接一个地为在IObservers列表中的每个Observer对象调用UpdateView().意味着,一旦notify方法被调用,所以注册的视图的UpdateView方法将自动被触发。 TObservable源代码如下所示: TObservable = class(TInterfacedObject, IObservable)private iObservers: TClassList; icurrentObject: TObject;public constructor Create; destructor Destroy; override; procedure setCurrentObject(o: TObject); procedure RegObserver(observer: IObserver); procedure Notify(o: TObject); property CurrentObject: TObject read icurrentObject write icurrentObject;end;.procedure TObservable.RegObserver(observer: IObserver);begin if iObservers = nil then iObservers := TClassList.Create; iObservers.Add(TClass(observer);end;procedure TObservable.Notify(o: TObject);var i: integer; observer: IObserver;begin if iObservers = nil then exit; if o = nil then exit; self.setCurrentObject(o); for i := 0 to iObservers.Count - 1 do begin observer := IObserver(iObservers.Itemsi); observer.UpdateView(o);/trigger the UpdateView function of IObserver end;end;3.2 MVC 3.2.1 Whats MVC? OK,我们现在己经知道观察者模式,现在,是时候学习些关于MVC的东西了。 让我们先简要回顾下观察者模式,你知道,观察者模式由两个主要部分组成,Observers和Observable对象,所有的Observers必须先被注册到Observable对象,因此假如在Observable对象中有任何数据变更,所有的Observers将被通知。这里的问题是谁将负责注册呢? 我想或许你也认识到依照观察者模式的规则,Observers通够查询Observable对象的状态并且依赖这些状态来更新自身,显然,这不够好,在真实的案例中,我们需要更多的交互,比如在ObServer中单击一个按纽,让Observable做一些事情和单击其他菜单或按纽做别的事情。让我们稍稍改造下观察者模式,在这里引入第三个东西,且赋给他在Observers和Observable对象间控制注册和通信的责任。因为他做所有的控制工作,故我们命名为控制器(Controller)。为了区别观察者模式,我们给被观察者(Observer)一个新名字-视图。然后给Observable(观察者)一个新名字-Model,OK,我们现在看到什么?Model,View和Controller,那就是MVC,不是吗? 那么,回答是:MVC是相当简单的,只是观察者模式加上一个控制器。 3.2.2 MVC in eMVC framework 图3.3是eMVC框加中的类定义模型,你或许认识到我没将TObservable改名到TModel,TObserver到IView,以便于一个设计能被两种模式所用,但是你知道Observer是视图,Observable是模式。就是那样。 3.2.2 MVC Set MVC框架引入一个新概念 MVC Set(mset). 1)它是什么? 一个mset必须只能有一个Controller,它或许包含一个(建议)或多个模型。每个模型有一个或多个注册的视图。一个mset完成实际的功能,在基于eMVC的应用程序里它被作为最小可重用的单元。 2)在一个基于eMVC的应用程序中可以有多少个msets? 到少一个,具体数量依赖于你的应用程序有多复杂和你如何组织他们。 3)这些mset如何被组织在一起? 基于eMVC的应用程序中所有的mset用职责链模式组织在一起。 3.3Chain of Responsibility(职责链) 3.3.1 CoR是什么? GOF设计模式一书中典型的职责链模式定义为: Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. 经由给多于一个对象一个处理数据的机会,以避免请求发送者到他的接收者之间的藕合。链接接收到象并沿着链路传递请求直到一个对象处理它。 典型的对象结构或许看起来象下图。 从上面的例示,我们可以概要如下: 1)多个处理器(Handler)可能会处理一个请求,但是仅有一个处理器实际的处理请求。 2)所有的处理器形成一个队列,一个处理器只有一个引用到下一个处理器。 3)请求者即不知道有多少个处理器可以处理它的请求也不知道哪一个处理器处理他的请求。 4)请求者对处理器没有任何控制能力。 5)处理器能被动态指定。 6)更改处理器列表将不会影响请求者代码。 3.3.2 Cor in eMVC 在Cor模式里,处理器负责处理请求,在MVC模式里,一个控制器(Controller)也负责处理一些事情,我们能统一他们吗?当然我们能。 在eMVC里,Controller实现了一个叫做SendCommand()的过程,这是标准CoR处理器的定义的名为HandleRequest()的另外一个名称.意味着所有的控制器(Controller)也能作为一个处理器,这使组织所有mset到COR模式中成为可能。 3.3.3 ControlCenter 1)ControlCenter是什么? 在告诉你ControlCenter是什么前,我们必须明白一个标准delphi应用程序中应用程序变量,在Delphi帮助文件中我找到是这样: Each GUI application automatically declares an Application variable as the instance of the application. If the Delphi application is not a Web server application, control panel applet, or NT service application, this variable is of type TApplication. 每个GUI应用程序自动定义了一个Application变量作为应用程序实例,如果Delphi应用程序不是一个Web Server应用程序,控制面板,或NT服务应用程序,这个变量是TApplication类型。 这里有一个标准的Proejct File. program Project1;uses Forms, Unit1 in Unit1.pas Form1;$R *.resbegin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run;end.Application是一个应用程序范围的变量以用于控制一个delphi程序,有些绕口不是吗?(英文有点)在eMVC,一个新的TControlCenter被定义以接管TApplication,命名为ControlCenter的TControlCenter实例被定义在每个基于eMVC的应用程序中。 这里有一个基于eMVC的Delphi项目文件,比较标准Delphi项目文件,你能在begin end对之间看不同之处。 program NewMVCApp;uses Forms, patterns,/include eMVC define unit MainCtrl in MainCtrl.pas, MainMdl in MainMdl.pas, MainView in MainView.pas ViewMain;$R *.resbegin ControlCenter.Run;end.ControlCenter只是隐藏了Application变量,并没有移除它,你仍然能在基于eMVC的应用程序的任何地方,任何时间使用Application变量,就像你在标准Delphi应用程序中编码一样。 2)如何注册一个新定义的Controller到ControlCenter 这非常容易,在每个Controller的初始块调用 ControlCenters的RegController()函数 initialization ControlCenter.RegController(TControllerMain.Create); /register to ControlCenter3)谁负责释放己注册的控制器 不用担心,所有注册的控制器在应用程序终止时被ControlCenter自动释放 3.4 还有什么? 我还需要知道什么?好,包括上面3个设计模式,理解和使用eMVC在你的开发工作中或许更有用,如果你花了一点时间在其他三个模式上的话:Tempate,Command 和SingleTon 4,核心组件 eMVC框架由几个base Classes组成,但是我们不必知道太多他们如何工作的细节。为了使用框架,下面的图例显示了我们需要知道的核心件。以便于我们开始使用框架。 This image has been resized to fit in the page. Click to enlarge.The core components of the eMVC library: TController. IObservable interface and TObservable class: IObserver interface: TControlCenter class TCommand class. 4.1 TController TController只是一个模板类,不要尝试实例化,应该定义一个派生自TController的你自己的控制器类。 因而一个典型的Controller类象下面这样。 type TControllerTypical = class (TController) protected Procedure DoCommand(Command: string; const args: string=); override; public Constructor Create; Destructor Destroy; override; end; 你己经知道,TController担当两个角色,第一是MVC模式的控制器,其次是CoR模式的处理器。 4.1.1 作为一个Controller(控制器) 控制器有两个主要任务,一个是注册所有的的Views到Model,这十分容易,另一个是在视图(Views)和Model(模型)之间控制交互与请求。或甚至是与其他控制器通信。 A TASK 1:注册视图到模型(向模型注册视图) 这个工作必须手工的在每个控制器的Create方法中完成。 Constructor TControllerMain.Create;begin inherited; model := TModelMain.Create; Application.CreateForm(TViewMain, view); model.RegObserver(view); /注册视图到模型end;你是否有多于一个视图,只要如以上代码调用模型的 RegObserver即可。 B TASK 2:逻辑控制 控制器支持从视图接收交互式请求。(鼠标或健盘输入).然后,依赖于这些请求,控制器能要求模型处理或发送请求到其他控制器。 这是易说不易实现的,在JAVA中,有很多预定义的Listener接口,比如如果你想一个类类能接受从一个标准 树状组件的选择(Selection)事件,只要实现TreeSelectionListener接口,且添加 你的类到TreeView的Listener列表。你的类就能接收和处理所有的选择事件。 不幸的是,delphi没有这种机制,eMVC也不能立即提供,因此,我们必须手工实现。 这儿,我展示了如何监控视图的所有按纽单击事件,让我们假定视图中有两个按钮,设置button1的Caption为&Close和button2的Caption为&About. Setp 1: 在你的视图类中添加一个public函数命名为 SetClickEvent ,或其它你喜欢的名字 type TViewMain = class(TFORM, IObserver) Button1: TButton; Button2: TButton; private Private declarations procedure UpdateView(o: TObject); /from IObserver 来自IObserver接口的方法 public Public declarations procedure setClickEvent(AEventHandler: TNotifyEvent); end;在实现区,定义函数实现如下: procedure TViewMain.setClickEvent(AEventHandler: TNotifyEvent);begin button1.OnClick := AEventHandler; button2.OnClick := AEventHandler;end;Step 2: 在Controller类中,添加一个私有(Private)方法名 OnClick typeTControllerMain = class(TController) model: TModelMain; view: TViewMain;Private . Procedure OnClick(Sender: TObject); / .end;实现如下: Procedure TControllerMain.OnClick(Sender: TObject);Begin If Sender is TButton then Begin If TButton(Sender).caption = &Close then View.close Else If TButton(Sender).caption = &About then Application.messageBox(About box); End;end;Step 3: 修改Controller的构造函数, 添加 View.SetClickEvent(OnClick); 。 Constructor TControllerMain.Create;begin inherited; model := TModelMain.Create; Application.CreateForm(TViewMain, view); model.RegObserver(view); view.setClickEvent(OnClick);end;现在每个按纽的单击事件将被Controller(控制器)捕捉。 C 一个简单的控制器类代码 unit MainCtrl;interfaceuses SysUtils, forms, buttons, classes, controls, patterns, MainMdl, MainView;type TControllerMain = class (TController) model: TModelMain; view: TViewMain; Private Procedure OnClick(Sender: TObject); / protected Procedure DoCommand(Command: string; const args: string=”); override; public Constructor Create; Destructor Destroy; override; end;implementationConstructor TControllerMain.Create;begin inherited; model := TModelMain.Create; Application.CreateForm(TViewMain, view); model.RegObserver(view); view.setClickEvent(OnClick);end;Destructor TControllerMain.destroy;begin freeAndNil(model); inherited;end;Procedure TControllerMain.DoCommand(Command: string; const args: string=”);beginend;Procedure TControllerMain.OnClick(Sender: TObject);Begin If Sender is TButton then Begin If TButton(Sender).caption = &Close then View.close Else If TButton(Sender).caption = &About then Application.messageBox(About box); End;end;initialization ControlCenter.RegController(TControllerMain.Create); /register to ControlCenter end.4.1.2 作为一个处理器 Be a handler 为了成为职择链模式的处理器,首先,控制器必须存入到链中,调用ControlCenter.RegController方法添加一个新定义的控制器到职责链。 其次,一个控制器必须有能力处理来自其他控制器的处理请求,不用说,也能发送请求,让我们看看用这种方法控制器是如何工作的。 A发送请求。 在 eMVC里,我们叫做Request command.两种Command能被使用。String Command和Object Command.细节参见4.5节。 发送一个Command很简单 Step 1, 在public单元定义一个唯一的具名(用户友好的,代表其意义的)常量字符串,不论你将使用哪种Command. Step 2, 使用SendCommand 方法发送Command.在TController类中定义了SendCommand的5种重载方法。依据Command类型和参数可任选一种。 procedure SendCommand(ACommand: ICommand; const args: TObject = nil); overload;procedure SendCommand(ACommand: string); overload;procedure SendCommand(ACommand: string; args: string); overload;procedure SendCommand(ACommand: string; args: TObject); overload;procedure SendCommand(ACommand: string; args: pointer); overload;B.处理请求 派生自TController的你的类中覆盖DoCommand方法 如果你想接受Object Command,覆盖这个: Procedure DoCommand(ACommand:ICommand;Const args:TObject=nil);如果你想接受无参数的String Command 覆盖这个: Procedure DoCommand(ACommand:String);如果你想接受有参数的String Command ,你有三种选择 Procedure DoCommand(ACommand:String;const args:String=);Procedure DoCommand(ACommand:String;const args:TObject=nil);procedure DoCommand(ACommand:String;const args:Pointer=nil);4.2 IObservable and TObservable Tobservable 默认实现IObservable接口,担当MVC模式中的MODEL(模型). 通常,我们建义一个新的模型类派生自IObservable.这儿有一个新定义的模型的样例: unit MainMdl;interfaceuses Classes, forms, SysUtils, patterns;type TModelMain = class(TObservable) public constructor Create; destructor Destroy; override; end;implementationconstructor TModelMain.Create;beginend;4.2.1模型的任务是什么? TASK 1: 为控制器服务 当控制器捕获视图的事件时,它将要求模型处理。比如做一些计算或者从数据库读取数据。意味着,模型必 须为控制器提供一系列的函数和过程。 TASK 2:为视图预备和提供弹药; 显示在视图上的任何东西(数据)都来自于模型。 4.2.2 如何通知? TObservable 有一个方法叫做 Notify(O:TObject).如果你想更新所有己注册的视图,调用这个方法。 4.2.3 通知什么? Tobservable上的Notify(O:TObject)有一个TObject类型的参数,包含着数据。他可以是派生自TObject的任何类。 4.2.4 在触发Notify方法后发生了什么? See Chapter 4.5 IObserver. 4.3 IObserver Interface 定义视图可能是开发基于eMVC应用程序最简单的工作了,只需实现IObServer接口 视图的祖先类可以是TForm,TFrame,TPanel,TTReeView或任何其他派生自TWinControl的类 unit MainView;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, StdCtrls, ComCtrls, ExtCtrls,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 烟台幼教考试题库及答案
- 新能源行业品牌塑造与市场推广策略报告2025:创新模式解析
- 儿童医学伤寒考试题
- 购销合同退回怎么写模板(3篇)
- 2025年感染性疾病科制度培训考核试卷(附答案)
- 2025年高中生航空航天知识竞赛题库及答案
- 2025新《公司法》知识竞赛题库(含参考答案)
- 2025年特种设备安全管理考试题库(含答案)
- 2025餐饮股东协议合同书
- 保洁员节假日后复工安全考核试卷含答案
- 长阳清江画廊
- 液压泵站使用说明书
- E190飞机舱门开关
- 儿科学腹泻病
- CT介入学及CT引导下肺穿活检术课件
- GB/T 3871.9-2006农业拖拉机试验规程第9部分:牵引功率试验
- GB/T 3836.4-2021爆炸性环境第4部分:由本质安全型“i”保护的设备
- GB 17840-1999防弹玻璃
- 文学鉴赏-课件
- 小军师面试万能绝杀模板-组织管理
- midasCivil斜拉桥分析课件
评论
0/150
提交评论