Yii 2.0 框架学习笔记-基础抽象

框架从 2.0 开始,底层抽象上面发生了一些变化。比如,多了 DI 和 Service Locator 等设计模式相关的抽象。这两天,专门看了下代码,写下一点我的想法。

上面的图是,是我用 Visual Paradigm 画的类图。从图里我们看到,2.0 版本以来,最根部的抽象是一个叫 Configurable 的接口,其主要作用就是说明所有的类都可以用类似 Key-Value 结构来进行配置。除了一些 Helper 的类,绝大部分对象都是 Configurable 的实现。

打开 Configurable 的代码,发现是一个空的接口,所以,我认为作者这是要表达一种抽象层面的概念,并没有实际的用途。查了 Stack-Overflow ,据说这是原自 Java 里的一种惯用做法,不过说实在的,我还是没有太理解,全空用来表达概念,可能是出于某种性能层面的考虑。但是,读起来确实有点故弄玄虚的错觉。

顶层的实体抽象其实是 Object,顾名思义,就是对象的基本抽象,对象的本质,应该有属性。于是 Object 主要提供了属性的抽象。这样,Object 就变成了一种非常纯粹的抽象。下面一层是 Component,名义上,这是组件,组件除了是一个对象以外,还有组件应有的核心抽象,是事件和行为。从 Component 的代码里,我们可以看到,它完全重新实现了关于属性的抽象。我想,这么做的原因大概是,Object 在实现属性的时候,只考虑了通用情况的做法,就是属性有对应的 getter 和 setter 进行包装,但是没有考虑到属性可以从 Behaviour 注入的情况,所以,组件完全重新实现了属性的抽象。显然另一种选择是单独实现 Behaviour 注入属性的情况,然后调用父类的普通属性的情况,但是为什么没这么做呢?这个我暂时也没有太多想法,估计也还是出于某种执行效率的考虑吧。

下面一层的抽象是 Service Locator,这是一个单独的对象,主要是 IoC 设计模式的一种实现,其本质是一种全局的注册表,里面记录了所有的 Service 的创建方法和位置。主要是用于在应用执行的过程中动态的引入 Service 的一种方式,使用这种方式,可以解开对特定 Service 的实现的依赖。另外,从 ServiceLocator 的代码里,我们也可以看到,这里还增加了 Lazy Loading 的策略在里面。某个具体的 Service 可以以配置数组的形态存在,直到真的需要的时候才实例化出来。实例化后,会被统一管理。

Module 是业务逻辑的基本组织单位,Module 自己就是一个 ServiceLocator。因为它是一个组织者,也是一个容器,这么抽象也是说得过去的。Module 控制着 Controller 和 View 的生命周期,此外 Module 还可以跟自己嵌套。所以,Module 就是 Yii 框架里,最核心的容器抽象了。帮助更有效的组织代码。

Application 是一种特殊的 Module,它是一个应用,整个系统启动的第一个容器。所以它是 Module 的子类。

另一边,Container 是 DI 设计模式的核心实现,主要就是容器。BaseYii 和 Yii 是全局的 Helper,这里也没看懂的,为啥 BaseYii 是个空类。Yii 这个 Helper 里面包含了 Container 的全局唯一实例,所以,所有的对象实例化的工作是由 Yii 完成的。

看完了 Yii 2.0 的抽象,我们再来回忆一下 1.0 的情况。第一,所有的对象也是可以配置的。但是没有用 Configurable 给把概念显性化出来。组件也是最核心的抽象,1.0 里的组件,包含了属性,事件,行为三种能力,这点跟 2.0 并无不同。区别在于,没有这么细腻的抽象层次,没有提供只含属性的 Object 抽象。

Module 在 1.0 里面,也是最核心的容器,也承载了对象构建,组件构建和组织的各种工作,本质上实现了 Service Locator 的功能,但是并没有把抽象识别出来。

综述一下,就是 2.0 的核心抽象,比起 1.0 来说,更加的细腻,完整,也更加灵活。但是,比起 1.0 并无实质性的突破,重要的功能 1.0 都提供了。所以,大可不必觉得 1.0 不如 2.0,我觉得在核心抽象层面,只是粗了一点,但是那些细腻真的是必要的么?恐怕也不是。我就看到程序员在实现业务的时候,不分青红皂白继承 Model,完全莫名奇妙的一个做法,可见大部分程序员,在具体实现代码的时候,并不关心核心抽象以及背后的设计思想。这倒也无可厚非,毕竟,使用 PHP 的程序员,有多大概率,能把项目发展到遇到抽象瓶颈的地步呢?

发表评论

电子邮件地址不会被公开。 必填项已用*标注