DTRouter 路由设计

文章内容转移到个人博客日后不会在简书中更新文章。​

随着移动互联网的不断发展,很多程序代码量和业务越来越多现有架构已经不适合公司业务的发展速度了,很多都面临着重构的问题。在公司项目开发中,如果项目比较小,普通的单工程+MVC架构就可以满足大多数需求了。但是像淘宝、蘑菇街、微信这样的大型项目,原有的简单架构就不足以满足架构需求了。

概要设计

看过很多开源路由框架,基本都是一个URL(与其说是URL 更应该为URL的规律)对应一个任务,如图:

keyvaluemap.png

那应该去想想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。把这些任务打包成一个代码块儿是个好办法。

目前为止,设计路由的思路已经很清晰了。

  1. pattern的规则定义
  2. 任务的展现方式选用

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的映射表就设计完了。

路由

simpleworkflow.png

路由的过程很简单,分析url 并分解为pattern实例和键值对,通过pattern实例查找对应的任务,并只用键值对执行block得到返回值并返回。

具体使用方法以及demo请查阅DTRouter by DreamTracer

参考资料:JLRoutesBeeHive

推荐阅读更多精彩内容