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 相关文章推荐
GD输出汉字的函数的分析
Oct 09 PHP
PHP 函数执行效率的小比较
Oct 17 PHP
php Rename 更改文件、文件夹名称
May 24 PHP
phpmail类发送邮件函数代码
Feb 20 PHP
深入解析Session是否必须依赖Cookie
Aug 02 PHP
php发送get、post请求的6种方法简明总结
Jul 08 PHP
PHP命名空间和自动加载类
Apr 03 PHP
Yii2实现让关联字段支持搜索功能的方法
Aug 10 PHP
基于ThinkPHP实现的日历功能实例详解
Apr 15 PHP
PHP实现简单的模板引擎功能示例
Sep 02 PHP
PHP5.6新增加的可变函数参数用法分析
Aug 25 PHP
php5.5使用PHPMailer-5.2发送邮件的完整步骤
Oct 14 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
常用星际术语索引(新手指南)
2020/03/04 星际争霸
PHP 加密与解密的斗争
2009/04/17 PHP
Thinkphp的volist标签嵌套循环使用教程
2014/07/08 PHP
php通过ksort()函数给关联数组按照键排序的方法
2015/03/18 PHP
JS隐藏参数post传值实例
2013/04/18 Javascript
JQuery打造省市下拉框联动效果
2014/05/18 Javascript
JavaScript严格模式禁用With语句的原因
2014/10/20 Javascript
深入分析下javascript中的[]()+!
2015/07/07 Javascript
JavaScrip调试技巧之断点调试
2015/10/22 Javascript
基于jQuery实现中英文切换导航条效果
2016/09/18 Javascript
学习使用jQuery表单验证插件和日历插件
2017/02/13 Javascript
将angular-ui的分页组件封装成指令的方法详解
2017/05/10 Javascript
JS按条件 serialize() 对应标签的使用方法
2017/07/24 Javascript
JS实现图片居中悬浮效果
2017/12/25 Javascript
vue2.0 兄弟组件(平级)通讯的实现代码
2018/01/15 Javascript
微信小程序左滑删除实现代码实例
2019/09/16 Javascript
autojs 蚂蚁森林能量自动拾取即给指定好友浇水的实现方法
2020/05/03 Javascript
webpack+vue-cil 中proxyTable配置接口地址代理操作
2020/07/18 Javascript
[02:47]2018年度DOTA2最佳辅助位选手4号位-完美盛典
2018/12/17 DOTA
[43:49]LGD vs CHAOS 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python实现从订阅源下载图片的方法
2015/03/11 Python
Python列表元素常见操作简单示例
2019/10/25 Python
python实现滑雪者小游戏
2020/02/22 Python
如何基于matlab相机标定导出xml文件
2020/11/02 Python
python3 kubernetes api的使用示例
2021/01/12 Python
Farfetch香港官网:汇集全球时尚奢侈品购物平台
2017/11/26 全球购物
《毛主席在花山》教学反思
2014/04/20 职场文书
村庄绿化方案
2014/05/07 职场文书
同学会邀请函模板
2015/01/30 职场文书
沈阳故宫导游词
2015/01/31 职场文书
教师工作证明范本
2015/06/12 职场文书
2015小学新教师个人工作总结
2015/10/14 职场文书
2015年小学语文教师工作总结
2015/10/23 职场文书
2019大学生暑期实习心得总结
2019/08/21 职场文书
python中的3种定义类方法
2021/11/27 Python
Java设计模式中的命令模式
2022/04/28 Java/Android