一个良好的MVC框架
最近重构一个项目,修改一个核心玩法,算下来代码量也有五千行以上吧,虽然原来的写法已经是一次重构的尝试了,但最后还是把各种对象关系搞得错综复杂,维护起来还是有点辛苦。我好久没有做过重构了,不过毕竟是带过十几万行代码项目的人,所以还是有两把刷子 的。
许多人都知道MVC,以及MVP,还有什么MVVM。模式有这么几种,而实践出来的,有更多种。但是各种各样的框架,都有各自的毛病,或者说如果只是照搬,那肯定是写不出好的框架来的。
我最近写的这个框架,其实还是基于MVC的思路去做的,M就是处理数据的,V就是处理呈现的,而C是处理关系的。在这里说一下,有的人有其他思路,例如他们把V当做纯粹的视图布局,而处理视图的逻辑,是放在C里实现的,安卓的Activity,IOS的ViewController,差不多就是这样子。这样做的原因是很多做应用的,逻辑都不会太复杂,所以简单的这么处理就足够了。
但是项目一旦变得复杂,一个Controller的代码让人读得难受的时候,这样的做法就失效了。所以我的做法是,C只是一个处理关系的对象,V不是那个纯粹的布局文件,而是各种视图交互的逻辑综合体,M是负责数据改变的。在V中改变数据的操作,会把操作通知C,C去寻找可以处理这个信息的M,M处理完后,修改数据/状态,数据/状态更新了后,会通知回C,C触发所有的V去更新自己的状态。每个V至少会绑定一个状态(数据集合体),凡是状态更新了的,V就会做一次刷新。
整个框架的思路就是这样。但是,有些不足的地方需要改进。试想,每次数据/状态更新的时候,V就要刷新,那要是这个数据/状态包含的内容比较多,那岂不是V刷新的内容也不少?另外,如果有好多个V,这些V要怎么知道自己是否需要刷新呢,难道每一帧都去检查一下自己绑定的数据/状态是否更新?
为了实现性能上的减负,使用一种折衷的办法来处理。每个V在绑定一个数据/状态的时候,就会把自己注册到数据/状态对象里去,数据/状态对象在每次更新的时候,就会把自己带着的V,通知给C,C得到了这些V,就直接去更新这些V就好了。
另外,数据/状态对象可以稍微再复杂一点,不仅仅是存一份数据/状态,而且还存一份改变的数据/状态的集合。这样V在更新的时候,就只更新这份集合里的变化,又可以减轻刷新的负担。
因为数据状态可能在同一个帧里被修改多次,如果每次一修改,就触发V更新的话,这样也不太好,所以往往是先让所有的该修改的数据/状态先更新,然后隔一帧,再处理所有的改变过的V的更新。
以上MVC的思路,可以让框架的代码分成3大块,每一块都各司其职。但是因为有些折衷的代码,所以,其实让人觉得不是很完美。为了更接近完美,那么就要好好利用面对对象的继承了。
前文说了,数据/状态为了让V的更新更加直接高效,需要把V注册到数据/状态中。这段逻辑可以封装到一个父类对象。例如,把V具体化为StateView,把数据/状态具体化为一个State。那么在XXState和XXStateView中就看不到这段逻辑。就可以更关注与本身变化的逻辑。