资讯专栏INFORMATION COLUMN

Laravel深入学习10 - 里氏替换原则

lijy91 / 2100人阅读

摘要:里氏替换原则该原则表示,程序中对于实例化对象的子类型,不需要修改代码,可以直接进行替换。上述实例已违背里氏替换原则。我们的数据库获取部分就是破坏里氏替换的点,在你以后的编码中一定要对这种编码留心

声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原汁性,另外因为是理解翻译,肯定会有错误的地方,欢迎指正。

欢迎转载,转载请注明出处,谢谢!

里氏替换原则 简介

别担心,里氏替换原则实际上比他的名字好理解。他是指任何在任何接受抽象化类的地方其实现也被接受。通俗的讲,类中使用接口实现的地方,不需要修改代码对于任意的接口实现类都将能使用。

里氏替换原则

该原则表示,程序中对于实例化对象的子类型,不需要修改代码,可以直接进行替换。

实探

我们继续拿OrderProcessor举例来阐述该原则,看下这个方法:

public function process(Order $order)
{
    // Validate order...

    $this->orders->logOrder($order);
}

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,
        ));
    }

}

现在,让我们检验下如何将不得不去使用此实现:

public function process(Order $order)
{
    // Validate order...

    if ($this->repository instanceof DatabaseOrderRepository)
    {
        $this->repository->connect("root", "password");
    }

    $this->repository->logOrder($order);
}

注意,在订单处理类中,我们强制检测了OrderRepositoryInterface是否为一个数据库的实现方式。如果是,继续数据库的连接。在小型应用中还算是小问题,但是,如果在很多其他类中OrderRepositoryInterface被使用到时怎么办?我们就只能在所有地方去添加这段“引导”代码。这样的代码维护让人头痛,还会代码潜在的bug,如果有一个地方忘记修改,就瞎了。

上述实例已违背里氏替换原则。在不修改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 (?, ?)", array(
            $order->id, $order->amount,
        ));
    }

}

现在在DatabaseOrderRepository中实现了数据库连接的管理,我们就可以从OrderProcessor中移除那段“引导”代码了:

public function process(Order $order)
{
    // Validate order...

    $this->repository->logOrder($order);
}

如此改变,我们就可以在OrderProcessor中随意使用CsvOrderRepository或者DatabaseOrderRepository了。我们的代码遵循了里氏替换原则。很多建筑学上的概念都被讨论成一种“认知”。特别的,对于每一个类,都有其自己的“语境”,他周边的代码在其依赖环境下帮助类来完成特定的工作。当你让架构朝着健壮方向发展的时候,这种类的设计“认知”将是一种持久重要的主题。

小心漏洞

你也许注意到了本原则和上章中提到的回避“抽象漏洞”类似。我们的数据库获取部分就是破坏里氏替换的点,在你以后的编码中一定要对这种编码留心!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/23043.html

相关文章

  • Laravel深入学习8 - 单一责任原则

    摘要:它是良好应用设计的大原则,包含单一责任原则开放封闭原则里氏替换原则接口分离原则依赖倒置原则让我们通过代码示例来深究下这五个原则。实探单一责任原则代表一个类有且仅有一个改变的原因,换言之,一个类的职责范畴是严谨明确的。 声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原...

    ymyang 评论0 收藏0
  • 深入理解JavaScript系列8:S.O.L.I.D五大原则里氏替换原则

    摘要:前言本章我们要讲解的是五大原则语言实现的第篇,里氏替换原则。因此,违反了里氏替换原则。与行为有关,而不是继承到现在,我们讨论了和继承上下文在内的里氏替换原则,指示出的面向对象。 前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle )。英文原文:http://fre...

    susheng 评论0 收藏0
  • 嘻哈说:设计模式之里氏替换原则

    摘要:定义按照惯例,首先我们来看一下里氏替换原则的定义。同样覆盖了父类的非抽象方法,并将逻辑更改为跳舞,这要是违背了里氏替换原则的。而重写显然是不符合里氏替换原则的。里氏替换原则的核心思想就是继承,所以优点就是继承的优点。 showImg(https://user-gold-cdn.xitu.io/2018/9/19/165f1897234ef1d4?w=600&h=350&f=jpeg&s...

    dendoink 评论0 收藏0
  • 设计模式7大原则

    摘要:在面向对象设计中,可维护性的复用是以设计原则为基础的。面向对象设计原则为支持可维护性复用而诞生,这些原则蕴含在很多设计模式中,它们是从许多设计方案中总结出的指导性原则。 面向对象设计原则 概述 对于面向对象软件系统的设计而言,在支持可维护性的同时,提高系统的可复用性是一个至关重要的问题,如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一。在面向对象设计中,...

    ky0ncheng 评论0 收藏0

发表评论

0条评论

lijy91

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<