PHP SPL标准库之接口(Interface)详解


Posted in PHP onMay 11, 2015

PHP SPL标准库总共有6个接口,如下:

1.Countable
2.OuterIterator
3.RecursiveIterator
4.SeekableIterator
5.SplObserver
6.SplSubject

其中OuterIterator、RecursiveIterator、SeekableIterator都是继承Iterator类的,下面会对每种接口作用和使用进行详细说明。

Coutable接口:

实现Countable接口的对象可用于count()函数计数。

class Mycount implements Countable

{

    public function count()

    {

        static $count = 0;

        $count++;

        return $count;

    }

}

 

$count = new Mycount();

$count->count();

$count->count();

 

echo count($count); //3

echo count($count); //4

说明:

调用count()函数时,Mycount::count()方法被调用
count()函数的第二个参数将不会产生影响

OuterIterator接口:

自定义或修改迭代过程。

//IteratorIterator是OuterIterator的一个实现类

class MyOuterIterator extends  IteratorIterator {

 

    public function current()

    {

        return parent::current() . 'TEST';

    }

}

 

foreach(new MyOuterIterator(new ArrayIterator(['b','a','c'])) as $key => $value) {

    echo "$key->$value".PHP_EOL;

}

/*

结果:

0->bTEST

1->aTEST

2->cTEST

*/

在实际运用中,OuterIterator极其有用:

$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'mckee');

$db->query('set names utf8');

$pdoStatement = $db->query('SELECT * FROM test1', PDO::FETCH_ASSOC);

$iterator = new IteratorIterator($pdoStatement);

$tenRecordArray = iterator_to_array($iterator);

print_r($tenRecordArray);

RecursiveIterator接口:
用于循环迭代多层结构的数据,RecursiveIterator另外提供了两个方法:

RecursiveIterator::getChildren 获取当前元素下子迭代器
RecursiveIterator::hasChildren 判断当前元素下是否有迭代器

class MyRecursiveIterator implements RecursiveIterator

{

    private $_data;

    private $_position = 0;

 

    public function __construct(array $data) {

        $this->_data = $data;

    }

 

    public function valid() {

        return isset($this->_data[$this->_position]);

    }

 

    public function hasChildren() {

        return is_array($this->_data[$this->_position]);

    }

 

    public function next() {

        $this->_position++;

    }

 

    public function current() {

        return $this->_data[$this->_position];

    }

 

    public function getChildren() {

        print_r($this->_data[$this->_position]);

    }

 

    public function rewind() {

        $this->_position = 0;

    }

 

    public function key() {

        return $this->_position;

    }

}

 

$arr = array(0, 1=> array(10, 20), 2, 3 => array(1, 2));

$mri = new MyRecursiveIterator($arr);

 

foreach ($mri as $c => $v) {

    if ($mri->hasChildren()) {

        echo "$c has children: " .PHP_EOL;

        $mri->getChildren();

    } else {

        echo "$v" .PHP_EOL;

    }

 

}

/*

结果:

0

1 has children:

Array

(

    [0] => 10

    [1] => 20

)

2

3 has children:

Array

(

    [0] => 1

    [1] => 2

)

*/

SeekableIterator接口:

通过seek()方法实现可搜索的迭代器,用于搜索某个位置下的元素。

class  MySeekableIterator  implements  SeekableIterator  {

 

    private  $position = 0;

 

    private  $array  = array(

        "first element" ,

        "second element" ,

        "third element" ,

        "fourth element"

    );

 

    public function  seek ( $position ) {

        if (!isset( $this -> array [ $position ])) {

            throw new  OutOfBoundsException ( "invalid seek position ( $position )" );

        }

 

       $this -> position  =  $position ;

    }

 

    public function  rewind () {

        $this -> position  =  0 ;

    }

 

    public function  current () {

        return  $this -> array [ $this -> position ];

    }

 

    public function  key () {

        return  $this -> position ;

    }

 

    public function  next () {

        ++ $this -> position ;

    }

 

    public function  valid () {

        return isset( $this -> array [ $this -> position ]);

    }

}

 

try {

 

    $it  = new  MySeekableIterator ;

    echo  $it -> current (),  "\n" ;

 

    $it -> seek ( 2 );

    echo  $it -> current (),  "\n" ;

 

    $it -> seek ( 1 );

    echo  $it -> current (),  "\n" ;

 

    $it -> seek ( 10 );

 

} catch ( OutOfBoundsException $e ) {

    echo  $e -> getMessage ();

}

/*

结果:

first element

third element

second element

invalid seek position ( 10 )

*/

SplObserver和SplSubject接口:
SplObserver和SplSubject接口用来实现观察者设计模式,观察者设计模式是指当一个类的状态发生变化时,依赖它的对象都会收到通知并更新。使用场景非常广泛,比如说当一个事件发生后,需要更新多个逻辑操作,传统方式是在事件添加后编写逻辑,这种代码耦合并难以维护,观察者模式可实现低耦合的通知和更新机制。
看看SplObserver和SplSubject的接口结构:

//SplSubject结构 被观察的对象

interface SplSubject{

    public function attach(SplObserver $observer); //添加观察者

    public function detach(SplObserver $observer); //剔除观察者

    public function notify(); //通知观察者

}

 

//SplObserver结构 代表观察者

interface SplObserver{

    public function update(SplSubject $subject); //更新操作

}

看下面一个实现观察者的例子:

class Subject implements SplSubject

{

    private $observers = array();

 

    public function attach(SplObserver  $observer)

    {

        $this->observers[] = $observer;

    }

 

    public function detach(SplObserver  $observer)

    {

        if($index = array_search($observer, $this->observers, true)) {

            unset($this->observers[$index]);

        }

    }

 

    public function notify()

    {

        foreach($this->observers as $observer) {

            $observer->update($this);

        }

    }

 

 

}

 

class Observer1 implements  SplObserver

{

    public function update(SplSubject  $subject)

    {

        echo "逻辑1代码".PHP_EOL;

    }

}

 

class Observer2 implements  SplObserver

{

    public function update(SplSubject  $subject)

    {

        echo "逻辑2代码".PHP_EOL;

    }

}

 

 

$subject = new Subject();

$subject->attach(new Observer1());

$subject->attach(new Observer2());

 

$subject->notify();

/*

结果:

逻辑1代码

逻辑2代码

*/
PHP 相关文章推荐
如何使用PHP获取网络上文件
Oct 09 PHP
改变Apache端口等配置修改方法
Jun 05 PHP
phpMyAdmin 安装及问题总结
May 28 PHP
win2003服务器使用WPS的COM组件的一些问题解决方法
Jan 11 PHP
PHP的5个安全措施小结
Jul 17 PHP
Web程序工作原理详解
Dec 25 PHP
php获取远程文件大小
Oct 20 PHP
php生成txt文件实例代码介绍
Apr 28 PHP
Laravel 5.3 学习笔记之 安装
Aug 28 PHP
PHP获取页面执行时间的方法(推荐)
Dec 10 PHP
基于php(Thinkphp)+jquery 实现ajax多选反选不选删除数据功能
Feb 24 PHP
php安装扩展mysqli的实现步骤及报错解决办法
Sep 23 PHP
PHP SPL标准库之文件操作(SplFileInfo和SplFileObject)实例
May 11 #PHP
PHP设计模式之适配器模式代码实例
May 11 #PHP
Mac环境下php操作mysql数据库的方法分享
May 11 #PHP
PHP设计模式之装饰者模式代码实例
May 11 #PHP
PHP超牛逼无限极分类生成树方法
May 11 #PHP
php以fastCGI的方式运行时文件系统权限问题及解决方法
May 11 #PHP
PHP获取当前日期和时间及格式化方法参数
May 11 #PHP
You might like
PHP中strtotime函数使用方法分享
2012/01/10 PHP
PHP编码转换
2012/11/05 PHP
ThinkPHP 3.2 数据分页代码分享
2014/10/14 PHP
Javascript中自动切换焦点实现代码
2012/12/15 Javascript
jQuery 2.0.3 源码分析之core(一)整体架构
2014/05/27 Javascript
JavaScript中的document.referrer在各种浏览器测试结果
2014/07/18 Javascript
微信小程序 安全包括(框架、功能模块、账户使用)详解
2017/01/16 Javascript
ES6新特性二:Iterator(遍历器)和for-of循环详解
2017/04/20 Javascript
浅谈Node.js轻量级Web框架Express4.x使用指南
2017/05/03 Javascript
JS使用tofixed与round处理数据四舍五入的区别
2017/10/25 Javascript
Angular网络请求的封装方法
2018/05/22 Javascript
Vue CL3 配置路径别名详解
2019/05/30 Javascript
javascript设计模式 ? 模板方法模式原理与用法实例分析
2020/04/23 Javascript
Vue Render函数创建DOM节点代码实例
2020/07/08 Javascript
vue 自定指令生成uuid滚动监听达到tab表格吸顶效果的代码
2020/09/16 Javascript
Python简单遍历字典及删除元素的方法
2016/09/18 Python
Python搭建HTTP服务器和FTP服务器
2017/03/09 Python
Python引用类型和值类型的区别与使用解析
2017/10/17 Python
python获取文件真实链接的方法,针对于302返回码
2018/05/14 Python
Django添加sitemap的方法示例
2018/08/06 Python
python生成以及打开json、csv和txt文件的实例
2018/11/16 Python
Python基本语法之运算符功能与用法详解
2019/10/22 Python
tensorflow使用range_input_producer多线程读取数据实例
2020/01/20 Python
JD Sports澳洲官网:英国领先的运动鞋和运动时尚零售商
2020/02/15 全球购物
维德科技C#面试题笔试题
2015/12/09 面试题
2014新年寄语
2014/01/20 职场文书
药品业务员岗位职责
2014/04/17 职场文书
竞选学习委员演讲稿
2014/09/01 职场文书
小班教师个人总结
2015/02/05 职场文书
大学教师个人总结
2015/02/10 职场文书
入学证明
2015/06/23 职场文书
老乡会致辞
2015/07/28 职场文书
情感电台广播稿
2015/08/18 职场文书
成本低的5个创业项目:投资小、赚钱快
2019/08/20 职场文书
详解Golang如何优雅的终止一个服务
2022/03/21 Golang
springboot用户数据修改的详细实现
2022/04/06 Java/Android