IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

静态类的原罪

火丁笔记 2011-08-17 13:48:02 累计浏览 2,592 次
本机暂存

    黑格尔有句名言:存在即合理。以此为论据的话,静态类的使用必然有其合理性。不过物极必反,一旦代码过于依赖静态类,那么必然会导致劣化。这就好比罂粟作为一种草本植物,有其在药理上的价值,但如果肆无忌惮的大量使用,它就变成了毒品。

什么是静态类

    所谓静态类指的是无需实例化成对象,直接通过静态方式调用的类。如下:

    此时类所扮演的角色更像是命名空间,这或许是很多人喜欢使用静态类最直接的原因。

静态类的问题

    本质上讲,静态类是面向过程的,因为通常它只是机械的把原本面向过程的代码集合到一起,虽然结果是以类的方式存在,但此时的类更像是一件皇帝的新衣,所以可以说静态类实际上是披着面向对象的壳儿,干着面向过程的事儿。

    面向对象的设计原则之一:针对接口编程,而不是针对实现编程。这有什么不同?打个比方来说:抛开价格因素,你喜欢独立显卡的电脑还是集成显卡的电脑?我想绝大多数人会选择独立显卡。独立显卡可以看做是针对接口编程,而集成显卡就就可以看做是针对实现编程。如此说来针对实现编程的弊端就跃然纸上了:它丧失了变化的可能性。

    下面杜撰一个文章管理系统的例子来具体说明一下:

    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

同分类推荐文章

  1. 如何写好设计文档? (2026-06-23 08:00:00)
  2. Designing With Uncertainty: How AI Supercharges Probabilistic Thinking (2026-06-16 23:00:00)
  3. The Benefits Of Cognitive Inclusion In UX Research (2026-06-10 18:00:00)

查看更多 设计 文章 →

建议继续学习

  1. 哪本书是对程序员最有影响、每个程序员都该阅读的书? (累计阅读 15,116)
  2. 在西方的程序员眼里,东方的程序员是什么样的? (累计阅读 9,919)
  3. 最常被程序员们谎称读过的计算机书籍 (累计阅读 9,159)
  4. JavaScript Interface 接口的实现 (累计阅读 6,992)
  5. PHP编码规范 (累计阅读 5,621)
  6. 用星际争霸讲解面向对象的概念 (累计阅读 5,223)
  7. 自己写的一个轻量级javascript框架的设计模式 (累计阅读 4,909)
  8. 关于架构的一句话,还有一个实例 (累计阅读 4,706)
  9. 弱爆程序员的特征值 (累计阅读 4,615)
  10. 如此理解面向对象编程 (累计阅读 4,561)