前端之家收集整理的这篇文章主要介绍了
Laravel深入学习10 - 里氏替换原则,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_
301_0@声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原汁性,另外因为是理解翻译,肯定会有
错误的地方,欢迎指正。
@H_
301_0@欢迎转载,转载请注明出处,谢谢!
里氏替换原则
简介
@H_
301_0@别担心,里氏替换原则实际上比他的名字好理解。他是指任何在任何接受抽象化类的地方其实现也被接受。通俗的讲,类中使用接口实现的地方,不需要
修改代码对于任意的接口实现类都将能使用。
@H_301_0@里氏替换原则
@H_301_0@该原则表示,程序中对于实例化对象的子类型,不需要修改代码,可以直接进行替换。
实探
@H_
301_0@我们继续拿
OrderProcessor
举例来阐述该原则,看下这个
方法:
public function process(Order $order)
{
// Validate order...
$this->orders->logorder($order);
}
@H_
301_0@在
Order
验证之后,我们使用
OrderRepositoryInterface
接口实现类来记录订单日志。我们假定,当订单处理未成熟时,我们将所有的订单以CSV格式记录到系统中。我们的额
OrderRepositoryInterface
接口实现类为
CsvOrderRepository
。当业务继续发展,我们想使用关系型
数据库记录订单。下面,我们看下一种可能的接口实现:
class DatabaSEOrderRepository implements OrderRepositoryInterface {
protected $connection;
public function connect($username,$password)
{
$this->connection = new DatabaseConnection($username,$password);
}
public function logorder(Order $order)
{
$this->connection->run('insert into orders values (?,?)',array(
$order->id,$order->amount,));
}
}
@H_
301_0@现在,让我们检验下如何将不得不去使用此实现:
public function process(Order $order)
{
// Validate order...
if ($this->repository instanceof DatabaSEOrderRepository)
{
$this->repository->connect('root','password');
}
$this->repository->logorder($order);
}
@H_
301_0@注意,在订单处理类中,我们强制检测了
OrderRepositoryInterface
是否为一个
数据库的实现方式。如果是,继续
数据库的连接。在小型应用中还算是小问题,但是,如果在很多其他类中
OrderRepositoryInterface
被使用到时怎么办?我们就只能在所有地方去
添加这段“引导”
代码。这样的
代码维护让人头痛,还会
代码潜在的bug,如果有一个地方忘记
修改,就瞎了。
@H_
301_0@上述实例已违背里氏替换原则。在不
修改connect
方法的情况下我们无法注入接口的实现类。既然发现了问题,那就去修复他们吧。这里是一个新的
DatabaSEOrderRepository
实现类:
class DatabaSEOrderRepository implements OrderRepositoryInterface {
protected $connector;
public function __construct(DatabaseConnector $connector)
{
$this->connector = $connector;
}
public function connect()
{
return $this->connector->bootConnection();
}
public function logorder(Order $order)
{
$connection = $this->connect();
$connection->run('insert into orders values (?,));
}
}
@H_
301_0@现在在
DatabaSEOrderRepository
中实现了
数据库连接的管理,我们就可以从
OrderProcessor
中移除那段“引导”
代码了:
public function process(Order $order)
{
// Validate order...
$this->repository->logorder($order);
}
@H_
301_0@如此改变,我们就可以在
OrderProcessor
中随意使用
CsvOrderRepository
或者
DatabaSEOrderRepository
了。我们的
代码遵循了里氏替换原则。很多建筑学上的概念都被讨论成一种“认知”。特别的,对于每一个类,都有其自己的“语境”,他周边的
代码在其依赖环境下帮助类来完成特定的工作。当你让架构朝着健壮方向发展的时候,这种类的设计“认知”将是一种持久重要的
主题。
@H_301_0@小心漏洞
@H_301_0@你也许注意到了本原则和上章中提到的回避“抽象漏洞”类似。我们的数据库获取部分就是破坏里氏替换的点,在你以后的编码中一定要对这种编码留心!