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中的array_filter()函数去掉多维空值的代码分享
Sep 07 PHP
PHP输出时间差函数代码
Jan 28 PHP
基于PHP array数组的教程详解
Jun 05 PHP
PHP如何利用P3P实现跨域
Aug 24 PHP
php权重计算方法代码分享
Jan 09 PHP
强制PHP命令行脚本单进程运行的方法
Apr 15 PHP
CodeIgniter控制器之业务逻辑实例分析
Jan 20 PHP
PHP调用Mailgun发送邮件的方法
May 04 PHP
PHP策略模式定义与用法示例
Jul 27 PHP
PHP编程实现阳历转换为阴历的方法实例
Aug 08 PHP
php静态成员方法和静态的成员属性的使用方法
Oct 26 PHP
PHP 对接美团大众点评团购券(门票)的开发步骤
Apr 03 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和javascript常用正则表达式及用法实例
2014/07/01 PHP
最常用的8款PHP调试工具
2014/07/06 PHP
WordPress网站性能优化指南
2015/11/18 PHP
PHP严重致命错误处理:php Fatal error: Cannot redeclare class or function
2017/02/05 PHP
分析php://output和php://stdout的区别
2018/05/06 PHP
PHP随机数函数rand()与mt_rand()的讲解
2019/03/25 PHP
jquery插件珍藏(图片局部放大/信息提示框)
2013/01/08 Javascript
节点的插入之append()和appendTo()的用法介绍
2014/01/13 Javascript
get(0).tagName获得作用标签示例代码
2014/10/08 Javascript
浅谈Vuejs中nextTick()异步更新队列源码解析
2017/12/31 Javascript
关于Webpack dev server热加载失败的解决方法
2018/02/22 Javascript
如何使用electron-builder及electron-updater给项目配置自动更新
2018/12/24 Javascript
浅谈webpack devtool里的7种SourceMap模式
2019/01/14 Javascript
Vue表单绑定的实例代码(单选按钮,选择框(单选时,多选时,用 v-for 渲染的动态选项)
2019/05/13 Javascript
[02:14]完美“圣”典2016风云人物:xiao8专访
2016/12/01 DOTA
[01:33:14]LGD vs VP Supermajor 败者组决赛 BO3 第二场 6.10
2018/07/04 DOTA
基于Python中capitalize()与title()的区别详解
2017/12/09 Python
Flask框架Flask-Login用法分析
2018/07/23 Python
python 异或加密字符串的实例
2018/10/14 Python
python实现剪切功能
2019/01/23 Python
实例讲解Python脚本成为Windows中运行的exe文件
2019/01/24 Python
python设置随机种子实例讲解
2019/09/12 Python
浅谈html5 video 移动端填坑记
2018/01/15 HTML / CSS
德国低价购买灯具和家具网站:Style-home.de
2016/11/25 全球购物
台湾租车首选品牌:IWS艾维士租车
2019/05/03 全球购物
星空联盟C# .net笔试题
2014/12/05 面试题
国贸专业的职业规划书
2014/03/15 职场文书
高中家长寄语
2014/04/02 职场文书
小学生环保演讲稿
2014/04/25 职场文书
六一儿童节标语
2014/10/08 职场文书
工作经历证明书范文
2014/11/02 职场文书
保安2014年终工作总结
2014/12/06 职场文书
小学生安全保证书
2015/05/09 职场文书
2019年警察入党转正申请书最新范文
2019/09/03 职场文书
详细聊聊浏览器是如何看闭包的
2021/11/11 Javascript
SQL Server 中的事务介绍
2022/05/20 SQL Server