文章内容转移到个人博客日后不会在简书中更新文章。
随着移动互联网的不断发展,很多程序代码量和业务越来越多,现有架构已经不适合公司业务的发展速度了,很多都面临着重构的问题。在公司项目开发中,如果项目比较小,普通的单工程+MVC架构就可以满足大多数需求了。但是像淘宝、蘑菇街、微信这样的大型项目,原有的简单架构就不足以满足架构需求了。
概要设计
看过很多开源路由框架,基本都是一个URL(与其说是URL 更应该为URL的规律)对应一个任务,如图:
那应该去想想URLPattern要用什么规则。
首先我们看一下我们在平时能看到的URL格式:
scheme://host/path?argument1=argumentValue1&argument2=argumentValue2
当然组合方式有很多,我只对如上格式的URL做了pattern分析。
这里我参考了一下JSRoutes的pattern。
比如我定义了一个pattern为:
dtrouter://:host/:path/hahaha/:otherpath
那么它就可以对应如下或者更多的url
dtrouter://router/pathhaha/hahaha/path2?arguemt1=argumentvalue1
dtrouter://router123/pathhahaasdf/hahaha/path456?arguemt1=argumentvalue1
可以看出 :host、:path、:otherpath部分是可变的,hahaha是不可变的,而且hahaha必须在第三个位置,后面的arguement 就看你需不需要了,JSRoutes 做了一个更好的处理,连hahaha的位置都是可选的。
pattern的规则已经选好了,接下来是task。
task指的是任务,我们希望访问一个url去执行一个任务。那这个任务是什么?
创建类、网络请求、查找数据库、push一个页面 等等。但是我没办法全面的考虑到开发者使用这个DTRouter具体要做什么,所以我需要把这些任务概括一下,而我的选择是Block。把这些任务打包成一个代码块儿是个好办法。
目前为止,设计路由的思路已经很清晰了。
- pattern的规则定义
- 任务的展现方式选用
Pattern与Task映射表
我打算用pattern为key,block为value的字典去存储映射关系。
value倒是好解决 ,直接存储就可以了存储之后类型为__NSGlobalBlock
那pattern怎么办?
我们都知道 NSDictionary的key必须是可哈希的。
NSObject默认以实例的内存地址为哈希的值。
回到话题,如果以内存地址为哈希值肯定不合适。
因为同样的pattern,可能是不同的对象,拥有不同的内存地址。
所以我打算重写isEqual和hashvalue 这两个方法,去根据pattern的内部属性去判断,是否为同一个pattern。
dtrouter://:host/:path 0x00000001
dtrouter://:host/:path 0x00000002
如果不重写以上两个方法,系统会视这两个pattern为不同的实例,但其实是同一个。
所以可能导致,字典中作为key的pattern相同。
这样pattern和task的映射表就设计完了。
路由
路由的过程很简单,分析url 并分解为pattern实例和键值对,通过pattern实例查找对应的任务,并只用键值对执行block得到返回值并返回。
具体使用方法以及demo请查阅DTRouter by DreamTracer