在MVC模式里controller处于一个核心的位置,它要负责接受从view发来的用户交互请求,将用户请求转发给商业对象进行处理,然后从商业对象获取处理结果,选择合适的视图呈现给用户。
也即controller有
如何监听view的操作?在delphi的VCL控件里封装了很多的事件,我们需要在controller里处理这些事件,然后在创建view时,把事件方法赋值给view里的控件,就实现了监听用户操作的功能。例如TInfoManagementView里有button->New,我们在controller里提供button的onclick方法(这是一个TNotifyEvent类型的事件方法),然后在TController.getInfoManagementView方法里将这个实现赋值给NewButton.OnClick = newClick即可。
至于调用model来处理用户请求,基础的工作就是在上述的监听事件里创建model实例,然后将用户输入更新到这个model实例,调用model相应的方法进行处理,获取处理结果即可。还是以New Button为例,我们在响应New Button的click事件时,首先调用getInfoEditView来为用户提供一个空白的信息输入界面(这里还没有设计到model),然后当用户输入完毕点击button Save提交,在controller.saveClick方法里,我们需要new一个model,然后将用户输入更新到model上,然后调用model.save保存至数据库。如果没有出错,就弹出一个“保存成功!”的提示框,用户点击“确定”或计时结束后回到managementView;如果保存失败,就弹出具体的错误信息,并保留在EditView上。
根据以上逻辑,controller的实现声明可以如下:
TController = class
private
FModel: IModel;
FManagementViewClass: TInfoManagementViewClass;
FInfoEditViewClass: TInfoEditViewClass;
procedure newButtonClick(Sender: TObject);
procedure saveButtonClick(Sender: TObject);
public
procedure showManagementView(parent: TWinControl);
procedure showEditView(Mode: TInfoMode);
end;
implemention
procedure TController.newButtonClick(Sender: TObject);
begin
with getEditView do
try
FModel := TModelFactory.getModelClass(className).create;
InfoMode := ifmdNew;
saveButton.onClick := saveClick;
if ShowModal = mrOK then
refreshList;
finally
FModel.free;
free;
end;
end;
procedure TController.saveButton(Sender: TObject);
begin
updateModel;
try
DBHelperFactory.getDBHelper.startTrans;
FModel.save;
DBHelperFactory.getDBHelper.commitTrans;
exception
on e: exception do
begin
DBHelperFactory.getDBHelper.rollbackTrans;
showmessage(e.message);
end;
end;
end;
procedure TController.showManagementView(parent: TWinControl);
var
view: TInfoManagementView;
begin
view := FManagementViewClass.create(parent);
if not assigned(parent) then
begin
view.showModal;
end
else
begin
view.parent := parent;
view.ManualDock(parent);
view.show;
end;
end;
procedure TController.showEditView(Mode: TInfoMode);
begin
with FInfoEditViewClass.Create(nil)
try
model := FModel;
InfoMode := Mode;
finally
free;
end;
end;
这样controller也搭建起来了;MVC模式就成为一个完整的框架。
controller的基础实现已经有了,但是我们不能也不应该在mainView(即主操作界面)里引用所有的controller,那末要如何实现呢?我们需要提供一个controllerFactory,mainView只需要知道controller的名称(不需要知道具体的controller类型),通过调用controllerFactory.getController(controllerName)即可获取到一个相应的controller实例。mainView又如何知道controller的名称呢,这就是mainController需要干的事情了。这涉及到具体的mainController实现逻辑,就不再累述了。