设计模式依赖倒置原则(DependenceInversionPrinciple)的定义是“高层模块不应该依赖低层模块,两者都应该依赖于它们的抽象;抽象不应该依赖于细节;细节应该依赖于抽象。”不难理解,但是在具体实现上,网上给出的很多PHP例子都是有缺陷的。以本文为例,概念上没有问题,但在实现上,尤其是代码中错误较多,不能体现PHP的特点。例如,在PHP中,您应该使用->而不是.调用方法和变量名应该有很多$之类的错误,就不说了。最重要的是,即使把这些语法错误全部改正,例子也不能说明原理,说服力不够。因为即使没有接口,没有抽象类,妈妈们依然可以给孩子讲故事,看报纸杂志。以下可运行代码不使用任何接口或抽象类。它还可以实现功能并且是可扩展的。它不需要修改Mother类中的任何代码。它还可以让妈妈轻松自如地阅读各种书籍。无非是加了各种各样的类,只要这个类有getContent方法,妈妈都能认出来:阿拉伯故事...\n";}}classNewspaper{publicfunctiongetContent(){return"林书豪17+9帮助尼克斯击败老鹰...\n";}}classMother{publicfunctionnarrate($book){echo"妈妈开始讲故事\n";echo$book->getContent();}}classClient{publicstaticfunctionmain(){$mother=newMother();$mother->narrate(newBook());$mother->narrate(newNewspaper());}}客户端::main();既然这么随意,怎么能体现依赖倒置呢?这是因为PHP是弱类型语言,其特点是不需要为变量指定类型。结果是只要你的类有我需要调用的方法(这里是getContent方法),那么无论如何都不会报错。至于你有没有实现什么interface接口,无所谓。这样,就不可能真正体现依赖倒置原则。那么如何才能真正体现依赖倒置呢?秘诀在于我们利用PHP的类型约束来指定narrate函数的$book参数必须是一个接口:echo$book->getContent();}}这里,我们规定$book参数必须是IReader接口,所以任何需要妈妈教的阅读材料都必须是IReader接口的实现,否则会报错。完整代码如下:getContent();}}classClient{publicstaticfunctionmain(){$mother=newMother();$mother->narrate(newBook());$mother->narrate(newNewspaper());}}$client=newClient();$client->main();可以尝试把Newspaper类后面的implementsIReader去掉再运行,马上报错:PHPFatalerror:UncaughtTypeError:Argument1passedtoMother::narrate()mustimplementinterfaceIReader,instanceofNewspapergiven,在第29行在/Users/zhangjing/Projects/phpdesignpattern/client.php中调用,在/Users/zhangjing/Projects/phpdesignpattern/client.ph中定义p:19所以结论是:对于PHP这样的弱类型语言,要想真正实现依赖倒置的原则,必须要加上类型约束,否则实现只是表象,不能真正体现出作用原则
