文档章节

From Apprentice To Artisan 翻译 19

zgldh
 zgldh
发布于 2015/03/19 18:23
字数 1867
阅读 1323
收藏 0

上一篇

Interface Segregation Principle 接口隔离原则

Introduction 介绍

The Interface Segregation principle states that no implementation of an interface should be forced to depend on methods it does not use. Have you ever had to implement methods of an interface that you did not need? If so, you probably created blank methods in your implementation. This is an example of being forced to use an interface that breaks the Interface Segregation principle.

接口隔离原则规定在实现接口的时候,不能强迫去实现没有用处的方法。你是否曾被迫去实现一些接口里你用不到的方法?如果答案是肯定的,那你可能创建了一个空方法放在那里。被迫去实现用不到的函数,这就是一个违背了接口隔离原则的例子。

In practical terms, this principle demands that interfaces be granular and focused. Sound familiar? Remember, all five SOLID principles are related, such that by breaking one you often must break the others. When breaking the Interface Segregation principle, the Single Responsibility principle must also broken.

在实际操作中,该原则要求接口必须粒度很细,且专注于一个领域。听起来很耳熟?记住,所有五个“坚实”原则都是相关的,也就是说当打破一个原则时,你通常肯定打破了其他的原则。在这里当你违背了接口隔离原则后,肯定也违背了单一职责原则。

Instead of having a "fat" interface containing methods not needed by all implementations, it is preferable to have several smaller interfaces that may be implemented individually as needed. By breaking fat interfaces into smaller, more focused contracts, consuming code can depend on the smaller interface, without creating dependencies on parts of the application it does not use.

“臃肿”的接口,有着很多不是所有的实现类都需要的方法。与其写这样的接口,不如将其拆分成多个小巧的接口,里面的方法都是各自领域所需要的。这样将臃肿接口拆成小巧、功能集中的接口后,我们就可以使用小接口来编码,而不必为我们不需要的功能买单。

Interface Segregation Principle 接口隔离原则

This principle states that no implementation of an interface should be forced to depend on methods it does not use.

该原则规定,一个接口的一个实现类,不应该去实现那些自己用不到的方法。如果需要,那就是接口设计有问题,违背了接口隔离原则。

In Action 实践

To illustrate this principle, let's consider an example session handing library. In fact, we will consider PHP's own SessionHandlerInterface. Here are the methods defined by this interface, which is included with PHP beginning in version 5.4:

为了说明该原则,我们来思考一个关于会话处理的类库。实际上我们将要考察 PHP 自己的SessionHandlerInterface。下面是该接口定义的方法,他们是从 PHP 5.4 版才开始有的:

<!-- lang:php -->
interface SessionHandlerInterface {
    public function close();
    public function destroy($sessionId);
    public function gc($maxLifetime);
    public function open($savePath, $name);
    public function read($sesssionId);
    public function write($sessionId, $sessionData);
}

Now that you are familiar with the methods defined by this interface, consider an implementation using Memcached. Would a Memcached implementation of this interface define functionality for each of these methods? Not only do we not need to implement all of these methods, we don't need half of them!

现在我们知道接口里面都是什么方法了,我们打算用Memcached来实现它。Memcached需要实现这个接口里的所有方法么?不,里面一半的方法对于Memcached来说都是不需要实现的!

Since Memcached will automatically expire the values it contains, we do not need to implement the gc method of the interface, nor do we need to implement the open or close methods of the interface. So, we are forced to define "stubs" for these methods in our implementation that are just empty methods. To correct this problem, let's start by defining a smaller, more focused interface for session garbage collection:

因为Memcached会自动清除存储的过期数据,我们不需要实现gc方法。我们也不需要实现openclose方法。所以我们被迫去写空方法来站着位子。为了解决在这个问题,我们来定义一个小巧的专门用来垃圾回收的接口:

<!-- lang:php -->
interface GarbageCollectorInterface {
    public function gc($maxLifetime);
}

Now that we have a smaller interface, any consuming code can depend on this focused contract, which defines a very narrow set of functionality and does not create a dependency on the entire session handler.

现在我们有了一个小巧的接口,功能单一而专注。需要垃圾清理的只用依赖这个接口即可,而不必去依赖整个会话处理。

To further understand the principle, let's reinforce our knowledge with another example. Imagine we have a Contact Eloquent class that is defined like so:

为了更深入理解该原则,我们用另一个例子来强化理解。想象我们有一个名为Contact的Eloquent类,定义成这样:

<!-- lang:php -->
class Contact extends Eloquent {
    public function getNameAttribute()
    {
        return $this->attributes['name'];
    }
    public function getEmailAttribute()
    {
        return $this->attributes['email'];
    }
}

Now, let's assume that our application also employs a PasswordReminder class that is responsible for sending password reminder e-mails to users of the application. Below is a possible definition of the PasswordReminder class:

现在我们再假设我们应用里还有一个叫PasswordReminder的类来负责给用户发送密码找回邮件。下面是PasswordReminder的定义方式的一种:

<!-- lang:php -->
class PasswordReminder {
    public function remind(Contact $contact, $view)
    {
        // Send password reminder e-mail...
    }
}

As you probably noticed, our PassswordReminder is dependent upon the Contact class, which in turns means it is dependent on the Eloquent ORM. It is neither desirable or necessary to couple the password reminder system to a specific ORM implementation. By breaking the dependency, we can freely change our back-end storage mechanism or ORM without affecting the password reminder component of the application. Again, by breaking one of the SOLID principles, we have given a consuming class too much knowledge about the rest of the application.

你可能注意到了,PasswordReminder依赖着Contact类,也就是依赖着Eloquent ORM。 对于一个密码找回系统来说,依赖着一个特定的ORM实在是没必要,也是不可取的。切断对该ORM的依赖,我们就可以自由的改变我们后台存储机制或者说ORM,同时不会影响到我们的密码找回组件。重申一遍,违背了“坚实”原则的任何一条,就意味着有个类它知道的太多了。

To break the dependency, let's create a RemindableInterface. In fact, such an interface is included with Laravel, and is implemented by the User model by default:

要切断这种依赖,我们来创建一个RemindableInterface接口。事实上Laravel已经有了这个接口,并且默认由User模型实现了该接口:

<!-- lang:php -->
interface RemindableInterface {
    public function getReminderEmail();
}

Once the interface has been created, we can implement it on our model:

一旦接口定义好了,我们就可以在模型上实现它:

<!-- lang:php -->
class Contact extends Eloquent implements RemindableInterface {
    public function getReminderEmail()
    {
        return $this->email;
    }
}

Finally, we can depend on this smaller, more focused interface in the PasswordReminder:

最终我们可以在PasswordReminder里面依赖这样一个小巧且专注的接口了:

<!-- lang:php -->
class PasswordReminder {
    public function remind(RemindableInterface $remindable, $view)
    {
        // Send password reminder e-mail...
    }
}

By making this simple change, we have removed unnecessary dependencies from the password reminder component and made it flexible enough to use any class from any ORM, so long as that class implements the new RemindableInterface. This is exactly how the Laravel password reminder component remains database and ORM agnostic!

通过这小小的改动,我们已经移除了密码找回组件里不必要的依赖,并且使它足够灵活能使用任何实现了RemindableInterface的类或ORM。这其实正是Laravel的密码找回组件如何保持与数据库ORM无关的秘诀!

Knowledge Is Power 知识就是力量

Again we have discovered the pitfalls of giving a class too much knowledge about application implementation details. By paying careful attention to how much knowledge we are giving a class, we can abide by all of the SOLID principles.

我们再次发现了一个使类知道太多东西的陷阱。通过小心留意是否让一个类知道了太多,我们就可以遵守所有的“坚实”原则。

下一篇

© 著作权归作者所有

共有 人打赏支持
zgldh
粉丝 95
博文 35
码字总数 46344
作品 2
高级程序员
私信 提问
From Apprentice To Artisan 翻译 20

上一篇 Dependency Inversion Principle 依赖反转原则 Introduction 介绍 We have reached our final destination in our overview of the five SOLID design principles! The final princip......

zgldh
2015/03/19
0
4
From Apprentice To Artisan 翻译 17

上一篇 Open Closed Principle 开放封闭原则 Introduction 介绍 Over the life time of an application, more time is spent adding to the existing codebase rather than constantly addi......

zgldh
2015/03/18
0
0
From Apprentice To Artisan 翻译 08

上一篇 As Organizer 作为管理工具 One of the keys to building a well architected Laravel application is learning to use service providers as an organizational tool. When you are ......

zgldh
2014/12/09
0
0
From Apprentice To Artisan 翻译 02

上一篇 Taking It Further 更进一步 Let's consider another example to solidify our understanding. Perhaps we want to notify customers of charges to their account. We'll define tw......

zgldh
2014/08/22
0
1
From Apprentice To Artisan 翻译 16

上一篇 Single Responsibility Principle 单一职责原则 Introduction 介绍 The "SOLID" design principles, articulated by Robert "Uncle Bob" Martin, are five principles that provide ......

zgldh
2015/03/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

聊聊storm的ICommitterTridentSpout

序 本文主要研究一下storm的ICommitterTridentSpout ICommitterTridentSpout storm-core-1.2.2-sources.jar!/org/apache/storm/trident/spout/ICommitterTridentSpout.java public interface......

go4it
18分钟前
1
0
Ubuntu常用操作

查看端口号 netstat -anp |grep 端口号 查看已使用端口情况 netstat -nultp(此处不用加端口号) netstat -anp |grep 82查看82端口的使用情况 查找被占用的端口: netstat -tln netstat -tl...

hc321
昨天
1
0
网站cdn的静态资源突然访问变的缓慢,问题排查流程

1.首先我查看了一下是否自己的网络问题,通过对比其他资源的访问速度和下载速度,确认不是 2.通过ping 和 tracert 判断cdn域名能否正常访问,(最后回想感觉这一步可以省略,因为每次最终能访...

小海bug
昨天
3
0
Mybatis 学习笔记四 MyBatis-Plus插件

Mybatis 学习笔记四 MyBatis-Plus插件 maven依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <ve......

晨猫
昨天
5
0
小白带你认识netty(二)之netty服务端启动(下)

承接上一篇小白带你认识netty(二)之netty服务端启动(上),还剩下两步骤:3、注册Selector:将Channel注册到Selector上 和 4、端口的绑定:服务端端口的监听。 3、注册Selector:将Chann...

天空小小
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部