********************************************************************
* 版权声明
*
* 本文以Creative Commons的发布,请严格遵循该授权协议。
* 本文首发于博客园, 此声明为本文章中不可或缺的一部分。
* 作者网名: 浪子
* 作者EMAIL:dayichen (at)163.com
* 作者BLOG: Http://Www.Cnblogs.Com/Walkingboy
*
********************************************************************
[Composite UI][设计模式]MVP or MVC?
-Written by 浪子@cnblogs.com (06-12-20)
摘要:
MVP or MVC?一直以来都认为CAB是MVP的典型应用,最近再考虑自己Web MVP框架中的MdiForm实现,记得CAB.WinForms 中有类似的实现MdiWorksapce,昨天看了下CAB的所有Hands On Labs的示例,发现它的例子都不采用MVP模式,感觉有点“误用”,也顺便想了下,利用CAB做到真正的MVP的思路,暂且记录一下。
一、老调重弹:MVP与MVC
MVP不同于MVC的地方,关键在于,View不再显示的依赖于business logic controller,而是依赖于一个业务逻辑抽象接口,关注于View的解藕。
所以区分MVP与MVC的关键在于View是否依赖于某一具体的业务对象。
二、CAB Labs之MVC
暂以CAB的Labs的代码为例,各层次之间的定义和关联如下:
CustomerWorkItem:驱动一个完整的Customer UseCase
CustomerDetailView:显示客户明细的UI
CustomerDetailController:包装CustomerWorkItem的关于Detail的功能,暴露服务接口给CustomerDetailView使用
关于CustomerDetailView中如何使用CustomerWorkItem
// We use our controller so we can show the comments page [CreateNew] public CustomerDetailController Controller { set { controller = value; } }
可以看到View只是依赖于OB的注入功能,采取对象注入的方式来获取Controller,但是其注入的类型却是具体的CustomerDetailController,而不是抽象对象(如IControlller),这样子虽然采用了IoC功能,但是依赖还是照样存在。
当然例子中有很多关于为View解藕的方法,比如EventBorker的Publisher和Subscriber,还有CommandHanlder,好像可以解决View的具体依赖问题,因为他们都依赖于抽象的WorkItem,但是当Controller也夹杂进来的时候,一下子就破坏了View的独立性。
三、CAB Labs之MVC重构
其实Labs中的依赖关键在于对具体Controller的依赖,如果我们可以将这部分进行重构,使之如同依赖于WorkItem一样依赖于一个IController就可以完全把View独立出来。
而如何抽象IController是关键点所在。
可能各种业务的Controller是不一样的,有的甚至背道而驰,如何抽象出他们的共同点是个难题所在。
我之前的框架是对其进行通用化,比如根据View的通过特性,定义一些跟View相关的约束:
public interface IController |
{ |
void ViewLoad; |
object LoadData; |
bool UpdateData; |
void ViewClose; |
//.... |
} |
Controller以配置文件为依据,注入View中,这样子解决View的职责(收集数据,展现数据)。
但是实际编码过程中发现,这种方式摒避了业务的特性,使得编码的时候,总觉得用起来大不顺手,有点隔靴搔痒的感觉。
那如何解决业务对象千变万化的问题呢?其实CAB中已经给出了绝佳的解决方法。
首先,弱化IController的接口约束功能,接口如下:
public interface IController { }
没有看错,是个空接口。那业务功能怎么办?别忘了WorkItem的实现方式,嘿嘿......
这个时候你会发现EventBroker&CommandHandler是如此的好用。通过配置将IView和IController进行结合,然后自动注册他们之间的关联Event和Command,你会发现编码又恢复到之前面向过程的方式,但是所有的组件之间又是松耦合的。
四、CAB Labs之MVP
上节中所说的还都是MVC,只不过利用CAB将Controller的具体依赖拨除而已,此时对于重构到MVP已经是水到渠成了。只要将控制的主动权转交到Presenter(由Controller重构而得)上就可以了。最简单的转化方式是,直接去除Labs示例中的Controller对象,直接将WorkItem作为Presenter对象,此时所有的依赖都消失,这也是我对Labs中为何加入一个Controller的对象疑惑之处,还没有发现它的优点所在。
以上思路纯属主观幻想,框架代码重构ing......