声明:本文非博主原创,来自《Laravel 4 From Apprentice to Artisan》阅读的翻译理解,当然不是原译,可以保证90%原创性,另外由于是理解翻译,难免有错误,欢迎指正。欢迎转载,转载请注明出处,谢谢!Liskov替换原则简介不用担心,Liskov替换原则其实比它的名字更容易理解。他的意思是,只要抽象类被接受,它的实现也会被接受。通俗地说,凡是在类中使用接口实现的地方,都可以用于任何接口实现类,无需修改代码。里氏替换原则这个原则是指对于程序中实例化对象的子类型,可以直接替换代码,无需修改代码。下面继续以OrderProcessor为例来说明这个原理。我们来看看这个方法:publicfunctionprocess(Order$order){//Validateorder...$this->orders->logOrder($order);}ValidateinOrder之后,我们使用OrderRepositoryInterface接口实现记录订单日志的类。我们假设当订单处理不成熟时,我们将所有订单以CSV格式记录到系统中。我们的OrderRepositoryInterface实现类是CsvOrderRepository。随着业务的不断发展,我们想使用关系型数据库来记录订单。接下来,让我们看看下一个可能的接口实现:classDatabaseOrderRepositoryimplementsOrderRepositoryInterface{protected$connection;publicfunctionconnect($username,$password){$this->connection=newDatabaseConnection($username,$password);}}publicfunctionlogOrder(Order$order){$this->connection->run('插入订单值(?,?)',array($order->id,$order->amount,));}}现在,让我们看看我们将如何使用这个实现:publicfunctionprocess(Order$order){//验证订单...('root','密码');}$this->repository->logOrder($order);}注意,在订单处理类中,我们强行检测OrderRepositoryInterface是否为数据库实现。如果是,则继续数据库连接。在小型应用程序中这是一个小问题,但如果在许多其他类中使用OrderRepositoryInterface怎么办?我们只能到处添加这个“引导程序”代码。这种代码维护很头疼,而且代码中存在潜在的bug。如果忘记修改一个地方,那你就瞎了。上面的例子已经违反了里氏代换原则。我们不能在不修改connect方法的情况下注入接口的实现类。既然问题已经找到了,那我们就来修复它们。这是一个新的DatabaseOrderRepository实现类:classDatabaseOrderRepositoryimplementsOrderRepositoryInterface{protected$connector;公共函数__construct(DatabaseConnector$connector){$this->connector=$connector;}publicfunctionconnect(){return$this->connector->bootConnection();}publicfunctionlogOrder(Order$order){$connection=$this->connect();$connection->run('插入订单值(?,?)',array($order->id,$order->amount,));}}现在数据库连接管理是在DatabaseOrderRepository中实现的,我们可以从OrderProcessor中删除“引导”代码:publicfunctionprocess(Order$order){//Validateorder...$this->repository->logOrder($order);}有了这个改动,我们就可以在OrderProcessor中自由使用CsvOrderRepository或者DatabaseOrderRepository了。我们的代码遵循Liskov替换原则。许多建筑概念被当作一种“认知”来讨论。特别是,对于每一个类,它都有自己的“上下文”,围绕他的代码帮助类在其依赖的环境中完成特定的任务。当您将架构推向稳健性时,这种设计“意识”一直是一个重要的主题。提防漏洞你可能已经注意到,这个原则类似于上一章提到的避免“抽象漏洞”。我们的数据库获取部分是破坏里氏替换的重点,以后编码一定要注意这个编码!