声明:本文非博主原创,来自《Laravel 4 From Apprentice to Artisan》阅读的翻译理解。当然不是原译,可以保证90%的原创性。另外,由于是理解翻译,难免有错误,欢迎指正。欢迎转载,转载请注明出处,谢谢!依赖倒置原则介绍我们已经达到了SOLID设计原则的最终目标愿景!依赖倒置原则,就是高层代码不能依赖低层代码。相应地,高层代码应该依赖一个抽象层,作为高层代码和低层代码之间的“中间人”。另一方面,原则是指抽象层不依赖于具体实现,而细节依赖于抽象。如果这看起来很神秘,请不要担心。我们将从以下两个方面详细阐述这一原则。依赖倒置原则这个原则是指高层代码不依赖低层代码,抽象不依赖具体细节。现实检验如果你读过本书前面的章节,你应该对依赖倒置有很好的理解。让我们通过下面的例子来解释它:classAuthenticator{publicfunction__construct(DatabaseConnection$db){$this->db=$db;}publicfunctionfindUser($id){return$this->db->e??xec('select*fromuserswhereid=?',array($id));}publicfunctionauthenticate($credentials){//验证用户...}}您可以猜到,Authenticator类负责查找和验证用户。让我们检查下一个类的构造函数。您可以看到我们有一个链接到数据库的DatabaseConnection实例。所以我们将验证器和数据库紧密耦合,这意味着用户对象必须建立在关系数据库查询之上。此外,我们的高级代码(Authenticator类)直接依赖于低级代码(DatabaseConnection类)。首先,我们解释“高级”和“低级”代码。底层代码实现了磁盘文件访问、数据库访问等功能,高层代码实现了对底层代码之上的逻辑功能的封装,但不能耦合进去。或者,高级代码依赖于构建在低级代码之上的抽象层,例如接口。不仅如此,底层代码_也_依赖于抽象层。让我们实现一个可以在Authenticator类中使用的接口:interfaceUserProviderInterface{publicfunctionfind($id);publicfunctionfindByUsername($username);}然后,将接口的实现注入到Authenticator中:$this->users=$users;}publicfunctionfindUser($id){return$this->users->find($id);}publicfunctionauthenticate($credentials){$user=$this->users->findByUsername($credentials['username']);返回$this->hash->make($credentials['password'])==$user->password;在这些更改之后,我们的Authenticator现在依赖于两个更高级别的抽象:UserProviderInterface和HasherInterface。我们可以自由地将接口的任何实现注入到Authenticator中。例如,如果我们的用户存储在Reids中,我们可以为UserProvider实现一个RedisUserProvider类。Authenticator不再直接依赖低级存储操作。此外,由于它实现了接口本身,我们的低级代码现在也依赖于高级UserProviderInterface抽象:}publicfunctionfind($id){$this->redis->get('users:'.$id);}publicfunctionfindByUsername($username){$id=$this->redis->get('user:id:'.$username);返回$this->find($id);}}思维倒置许多开发人员在他们的应用程序中使用_倒置_原则。与高级代码直接耦合到低级代码的这种“自上而下”方法不同,该原则意味着高级和低级代码“同时”依赖于高级抽象层。在我们“反转”Authenticator的依赖关系之前,它不能在其他数据存储系统中使用。在改变存储系统的情况下,必须修改Authenticator,违反了开放封闭原则。我们已经知道有几个原则是相互渗透的。在将Authenticator强制实现在存储层之上的抽象层,我们可以根据UserProviderInterface接口约定切换到任何其他存储系统,而无需修改Authenticator本身。传统的依赖关系可以“倒转”,让代码变得非常灵活,易于更改!
