Laravel深入学习11 - 接口分离原则

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

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

接口分离原则

介绍

接口分离原则指在实现类中对于接口中的方法并不强制去实现使用不到的方法。事实上,在平时的代码中,你也难道也实现了那些你不需要使用的接口方法?如果是,也是流程空方法吧。这其实已经违背了接口分离原则。

实际上,本原则要求接口必须是粒度明确的。听起来是否似曾相识?是的,SOLID原则都是相关的,打破其中一条,基本上你也就打破了其他原则。当你的代码不符合接口分离原则时,那也肯定违背了单一责任原则。

代替这种在实现类中包含很多“笨重”方法的接口,我们把他划分成很多细小需要集成的多个接口。通过把臃肿的接口切成小的,细分的约定,使代码可以继承较小的接口,而不需创建引用中不需要依赖的部分。

接口分离原则

本原则是指在实现类中对于接口中的方法并不强制去实现使用不到的方法。

实探

为了阐述该原则,我们来以会话处理类库举例。实际上,我们参考PHP自带的SessionHandlerInterface接口。下面是PHP5.4中接口定义的方法:

interface SessionHandlerInterface {
    public function close();
    public function destroy($sessionId);
    public function gc($maxLiftetime);
    public function open($savePath, $name);
    public function read($sessionId);
    public function write($sessionId, $sessionData);
}

这些接口中的方法很熟悉了吧,考虑基于Memcached实现的解决方案。是不是以Memcached实现的接口类必须将所有方法实现?我们不仅不需要实现所有的方法,其中一般都不需要处理!

Memcached有自己的自动过期机制,因此我们不需要实现接口的gc方法,也不需要实现open或者close方法。这里我们只需定义一个空方法。为了纠正这个问题,我们来定义一个更小,更专注的接口来进行session垃圾回收:

interface GarbageCollectorInterface {
    public function gc($maxLifetime);
}

现在接口已经很小,所有相关代码都能依赖这个专们的约定,它定义了一个专门的函数无需处理所有的session操作。

我们来以另外一个例子来加深对该原则的理解。这里有一个ContactEloquent类是这样定义的:

class Contact extends Eloquent {

    public function getNameAttribute()
    {
        return $this->attributes['name'];
    }

    public function getEmailAttribute()
    {
        return $this->attributes['email'];
    }

}

现在,假定应用同样使用了PasswordReminder类来发送密码提醒邮件给用户。下面是PasswordReminder可能的一种实现类:

class PasswordReminder {

    public function remind(Contact $contact, $view)
    {
        // Send password reminder e-mail...
    }

}

你应该已经注意到,PasswordReminder以来了Contact类,也就意味着他依赖了Eloquent ORM。这种特殊的以ORM实现的密码提醒系统来说是不合理也是不需要的。在这种依赖之外,我们能自由的切换后台存储机制或者ORM而不用改变现有的密码提醒组件。又一次,我们破坏了SOLID原则,现有的类对应用中的其他“认知”知道的太多了。

为了打破这种依赖,我们来创建一个RemindableInterface接口。实际上,这个接口已经包含在Laravel中了,默认已经实现在User模型中了:

interface RemindableInterface {
    public function getReminderEmail();
}

接口一旦创建完毕,我们就可以在模型中来实现他:

class Contact extends Eloquent implements RemindableInterface {

    public function getReminderEmail()
    {
        return $this->email;
    }

}

最终,我们只须要依赖这个结构更小,功能更专注的PasswordReminder接口:

class PasswordReminder {

    public function remind(RemindableInterface $remindable, $view)
    {
        // Send password reminder e-mail...
    }

}

简单的改变,我们的类实现新的RemindableInterface之后,我们就将密码提醒组件中不需要的依赖剔除,相对ORM就更加具有灵活性了。这也是Laravel在数据库和ORM之外对密码提醒组件的实现。

只是就是力量

再次地,我们发现类中太多的实现细节带来的陷阱。对类中给定的职责多加注意,我们就能很好的遵守SOLID设计原则。

    原文作者:laravel
    原文地址: https://segmentfault.com/a/1190000009623392
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞