PHP接口是什么?
接口是两个PHP对象之间的契约,其目的不是让一个对象依赖另一个对象的身份,而是依赖另一个对象的能力。
接口把我们的代码和依赖解耦了,而且允许我们的代码依赖任何实现了预期(能力)接口的第三方代码。
我们不管第三方代码是如何实现接口的,我们只关心第三方代码是否实现了指定的接口(功能)。
案例:
我需要实现一个收集文本的功能。
class DocumentStore { protected $data = []; public function addDocument(Documentable $document) { $key = $document->getId(); $value = $document->getContent(); $this->data[$key] = $value; } public function getDocuments() { return $this->data; } }
addDocument方法的参数是Documentable类的实例(对象),此处需要注意的是,如果addDocument方法的参数,是Documentable类的实例,那么,DocumentStore的功能将被限定,只能从Documentable类来获取文本信息。
所以,此处Documentable不是类,而是一个接口,定义如下:
interface Documentable { public function getId(); public function getContent(); }
这个接口表明,实现Documentable接口的任何对象必须提供一个公开的getId方法和一个公开的getContent方法。
这么做的作用是什么呢?
这么做的作用是,我们可以分开定义获取文本的类,而且能使用不同的实现方式。
// 获取HTML文本 class HtmlDocument implements Documentable { protected $url; public function __construct($url) { $this->url = $url; } public function getId() { return $this->url; } public function getContent() { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_MAXREDIRS, 3); $html = curl_exec($ch); curl_close($ch); return $html; } }
// 从流中读取文本 class StreamDocument implements Documentable { protected $resource; protected $buffer; public function __construct($resource, $buffer = 4096) { return 'resource-' . (int)$this->resource; } public function getContent() { $streamContent = ''; rewind($this->resource); while (feof($this->resource) === false) { $streamContent .= fread($this->resource, $this->buffer); } return $streamContent; } }
// 获取终端执行文档 class CommandOutputDocument implements Documentable { protected $command; public function __construct($command) { $this->command = $command; } public function getId() { return $this->command; } public function getContent() { return shell_exec($this->command); } }
使用
$documentStore = new DocumentStore(); // 添加html文档 $htmlDocument = new HtmlDocument('http://php.net'); $documentStore->addDocument($htmlDocument); // 添加流文档 $streamDocument = new StreamDocument(fopen('test.txt', 'rb')); $documentStore->addDocument($streamDocument); // 添加终端命令文档 $commanDocument = new CommandOutputDocument('cat /etc/hosts'); $documentStore->addDocument($commanDocument); print_r($documentStore->getDocuments());
以上,DocumentStore类的实例,通过依赖实现了Documentable接口的HtmlDocument,StreamDocument,CommandDocument来获取文档内容。
需要注意的是,DocumentStore是依赖HtmlDocument,StreamDocument,CommandDocument的能力,就是通过实现Documentable接口,重写接口getId,getContent方法,来获取文档ID和内容,根本不关系接口实现类的内部实现方式。