欢迎您访问我爱IT技术网,今天小编为你分享的编程技术是:【静态类的原罪】,下面是详细的分享!
静态类的原罪
黑格尔有句名言:存在即合理。以此为论据的话,静态类的使用必然有其合理性。不过物极必反,一旦代码过于依赖静态类,其劣化的解决则不可避免。这就好比罂粟作为一种草本植物,有其在药理上的价值,但如果肆无忌惮的大量使用,它就变成了毒品。
什么是静态类
所谓静态类指的是无需实例化成对象,直接通过静态方式调用的类。代码如下:
class Math
{
public static function ceil($value)
{
return ceil($value);
}
public static function floor($value)
{
return floor($value);
}
}
?>
此时类所扮演的角色更像是命名空间,这或许是很多人喜欢使用静态类最直接的原因。
静态类的问题
本质上讲,静态类是面向过程的,因为通常它只是机械的把原本面向过程的代码集合到一起,虽然结果是以类的方式存在,但此时的类更像是一件皇帝的新衣,所以可以说静态类实际上是披着面向对象的壳儿,干着面向过程的事儿。
面向对象的设计原则之一:针对接口编程,而不是针对实现编程。这有什么不同?打个比方来说:抛开价格因素,你喜欢独立显卡的电脑还是集成显卡的电脑?我想绝大多数人会选择独立显卡。独立显卡可以看做是针对接口编程,而集成显卡就就可以看做是针对实现编程。如此说来针对实现编程的弊端就跃然纸上了:它丧失了变化的可能性。
下面杜撰一个文章管理系统的例子来具体说明一下:
class Article
{
public function save()
{
ArticleDAO::save();
}
}
?>
Article实现必要的领域逻辑,然后把数据持久化交给ArticleDAO去做,而ArticleDAO是一个静态类,就好像焊在主板上的集成显卡一样难以改变,假设我们为了测试代码可能需要Mock掉ArticleDAO的实现,但因为调用时使用的是静态类的名字,等同于已经绑定了具体的实现方式,Mock几乎不可能,当然,实际上有一些方法可以实现:
class Article
{
private static $dao='ArticleDAO';
public static funciton setDao($dao)
{
self::$dao=$dao;
}
public static function save()
{
$dao=self::$dao;
$dao::save();
}
}
?>
有了变量的介入,可以在运行时设定具体使用哪个静态类:
Article::setDao('MockArticleDAO');
Article::save();
?>
虽然这样的实现方式看似解决了Mock的问题,但是首先它修改的原有的代码,违反了开闭原则,其次它引入了静态变量,而静态变量是共享的状态,有可能会干扰其它代码的执行,所以并不是一个完美的解决方案。
补充说明,利用动态语言的特性,其实可以简单的通过require一个不同的类定义文件来实现Mock,但这样做同样有弊端,设想我们在脚本里需要多次变换实现方式,但实际上我们只有一次require的机会,否则就会出现重复定义的错误。
注:某些情况下,利用静态延迟绑定也可以提高静态类的可测试性,参考PHPUnit。
对象的价值
如果放弃静态类,转而使用对象,应该如何实现文章管理系统的例子?代码如下:
class Article
{
private $dao;
public function __construct($dao=null)
{
if ($dao===null) {
$dao=new ArticleDAO();
}
$this->setDao($dao);
}
public function setDao($dao)
{
$this->dao=$dao;
}
public function save()
{
$this->dao->save();
}
}
?>
实际上,这里用到了人们常说的依赖注入技术,通过构造器或者Setter注入依赖的对象:
$article=new Article(new MockArticleDAO());
$article->save();
?>
对象有自己的状态,不会发生共享状态干扰其它代码的执行的情况。
…
当然,静态类有好的一面,比如说很适合实现一些无状态的工具类,但多数时候,我的主观倾向很明确,多用对象,少用静态类,避免系统过早的固化。顺便说一句,希望别有人告诉我静态类比对象快之类的说教,谢谢。(来源:火丁笔记)
以上所分享的是关于静态类的原罪,下面是编辑为你推荐的有价值的用户互动:
相关问题:人类的原罪都有哪些
答:原罪 ----(Original sin)一词来自基督教的传说,它是指人类生而俱来的、洗脱不掉的“罪行”。圣经中讲:人有两种罪--原罪与本罪,原罪是始祖犯罪所遗留的罪性与恶根,本罪是各人今生所犯的罪。 原罪的教义是基督教重要的基础教义。我们的基督教清... >>详细
相关问题:谁知道人类10大原罪是什么?
答:原罪一词来自基督教,但是基督教里原罪只有七个,分别是:傲慢(Pride) 嫉妒(Envy) 暴怒(Wrath) 懒惰(Sloth) 贪婪(Greed) 饕餮(Gluttony) 欲望(Lust)。 基督教认为,亚当、夏娃偷吃“禁果”,违背上帝的意志,是“亏欠了上帝的荣耀”,这罪遗传给后世... >>详细
相关问题:人类的原罪有哪些?
答:愤怒,贪婪,嫉妒,傲慢,懒惰,懦弱,色欲,虚荣,贪食!此为人的九大原罪! >>详细
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
