静态类的原罪
黑格尔有句名言:存在即合理。以此为论据的话,静态类的使用必然有其合理性。不过物极必反,一旦代码过于依赖静态类,那么必然会导致劣化。这就好比罂粟作为一种草本植物,有其在药理上的价值,但如果肆无忌惮的大量使用,它就变成了毒品。
什么是静态类
所谓静态类指的是无需实例化成对象,直接通过静态方式调用的类。如下:
此时类所扮演的角色更像是命名空间,这或许是很多人喜欢使用静态类最直接的原因。
静态类的问题
本质上讲,静态类是面向过程的,因为通常它只是机械的把原本面向过程的代码集合到一起,虽然结果是以类的方式存在,但此时的类更像是一件皇帝的新衣,所以可以说静态类实际上是披着面向对象的壳儿,干着面向过程的事儿。
面向对象的设计原则之一:针对接口编程,而不是针对实现编程。这有什么不同?打个比方来说:抛开价格因素,你喜欢独立显卡的电脑还是集成显卡的电脑?我想绝大多数人会选择独立显卡。独立显卡可以看做是针对接口编程,而集成显卡就就可以看做是针对实现编程。如此说来针对实现编程的弊端就跃然纸上了:它丧失了变化的可能性。
下面杜撰一个文章管理系统的例子来具体说明一下:
Article是一个领域对象,ArticleDAO是一个数据访问对象,Article完成一些必要的领域逻辑,然后把数据持久化工作交给ArticleDAO去做,ArticleDAO是一个静态类,它被硬编码写死在程序里,就好像焊在主板上的集成显卡一样难以改变,假设我们为了测试代码可能需要Mock掉ArticleDAO的实现,但因为调用时使用的是静态类的名字,等同于已经绑定了具体的实现方式,想Mock变的几乎不可能,当然,实际上有一些方法可以实现:
有了变量的介入,静态类才可能实现Mock,你可以在运行时设定具体使用哪个静态类:
虽然这样的实现方式看似解决了Mock的问题,但是它引入了静态变量,而静态变量是共享的状态,有可能会干扰其它代码的执行,所以并不是一个完美的解决方案。
注:某些情况下,利用静态延迟绑定也可以提高静态类的可测试性,参考PHPUnit。
对象的价值
如果放弃静态类,转而使用对象,应该如何实现文章管理系统的例子?代码如下:
dao = $dao; } public function setDao($dao) { $this->dao = $dao; } public function save() { $this->dao->save(); } } ?>
实际上,这里用到了人们常说的依赖注入技术,通过构造器或者Setter注入依赖的对象:
save(); ?>
…
当然,静态类有好的一面,比如说很适合实现一些无状态的工具类,但多数时候,我的主观倾向很明显,多用对象,少用静态类,避免系统过早的固化。顺便说一句,希望别有人告诉我静态类比对象快之类的说教,谢谢。
相关链接:static considered harmful
建议继续学习:
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:老王 来源: 火丁笔记
- 标签: 静态类
- 发布时间:2011-08-17 13:48:02
- [69] 如何拿下简短的域名
- [68] Go Reflect 性能
- [66] Oracle MTS模式下 进程地址与会话信
- [61] 图书馆的世界纪录
- [61] IOS安全–浅谈关于IOS加固的几种方法
- [60] 【社会化设计】自我(self)部分――欢迎区
- [59] android 开发入门
- [56] 视觉调整-设计师 vs. 逻辑
- [48] 给自己的字体课(一)——英文字体基础
- [48] 读书笔记-壹百度:百度十年千倍的29条法则