lanyu 2014-06-20
在前端控制器中说到执行命令时,是用命令对象自己调用视图,如果系统的规模较小,可以如此。但这并不是最佳的选择,最好是尽可能地将命令和视图分离开来。
一、概念
应用控制器负责映射请求到命令,并映射命令到视图。这种分离意味着可以更加容易地改变视图(即模板)而不用改动核心代码。同时,也可以改变应用程序的流程而不需要修改核心部分的代码。通过将Command分离出来,可以更加容易地把同一个Command用在系统中的不同地方。
二、为什么要使用应用控制器?
假设用户需要关注一个好友(Friend),并通知被关注者,即发送消息(Feeds),因此系统需要支持AddFriend和SendFeeds命令,我们可以直接使用请求参数(cmd=AddFriend)将命令映射到一个类。如果AddFriend执行成功,SendFeeds命令将被调用,然后SendFeeds加载一个视图,这种关系可以硬编码到类本身。这种处理方式随着系统中命令类的不断增加,麻烦也接踵而至。比如现在要让AddFriend使用特定的视图,并且想要修改AddFriend调用SendFeeds的逻辑,那么你应该将命令间的关系及命令与视频间的关系的硬编码全部修改。
应用控制器可以替你完成这个工作,把Command解放出来,让Command集中处理自己的工作,包括处理输入、调用应用程序和处理结果等。
三、实现应用控制器
其实实现的方法仁者见仁,智者见智,关键在于模式中参与者(应用控制器、命令和视图等)互相通信的方式,而不是实现的细节,下面简单介绍一种通过xml配置文件来实现的方式。
第一步:配置文件
<woo-options> <dsn>sqlite://./data/woo.db</dsn> <control> <view>main</view> <view status="CMD_OK">main</view> <view status="CMD_ERROR">error</view> <command name="ListFriend"> <view>listvenues</view> </command> <command name="QuickAddFriend"> <classalias name="AddFriend" /> <view>quickadd</view> </command> <command name="AddFriend"> <view>addfriend</view> <status value="CMD_OK"> //如果操作成功,则前进到下一步SeedFeeds <forward>SendFeeds</forward> </status> </command> <command name="SendFeeds"> <view>seedfeeds</view> <status value="CMD_OK"> <forward>ListFriend</forward> </status> </command> </control> </woo-options>
第二步:解析文件
就是解析上面的xml,此步可以放在前端控制器中的ApplicationHelper中进行。
第三步:存储配置数据
上一步解析后的数据利用注册表进行存储
第四步:根据配置数据,完成命令的迭代
通过前端控制器处理请求,根据请求参数查找第三步存储配置数据,获取Command,根据status,选择结束还是forward,结束则获取view,forward则进行下一步Command。
四、总结
应该发现,要实现一个完整的应用控制器模式是相当困难的,需要做很多的工作,包括得到和应用元数据来描述命令与请求、命令与命令以及命令与视图之间的关系。因此,最好只在项目需要时才这样做。我当在命令类中添加条件语句来加载不同的视图或者调用不同命令时,如果觉得命令与显示的逻辑不太容易控制,才会相到使用应用控制器。
当然,正我之前所说,应用控制器的实现方式有很多种,而不仅限于上面介绍的那个方法。