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 和 MYSQL
Oct 09 PHP
Ping服务的php实现方法,让网站快速被收录
Feb 04 PHP
深入php之规范编程命名小结
May 15 PHP
php中filter函数验证、过滤用户输入的数据
Jan 13 PHP
ci检测是ajax还是页面post提交数据的方法
Nov 10 PHP
php获取四位字母和数字的随机数的实现方法
Jan 09 PHP
ecshop实现smtp发送邮件
Feb 03 PHP
Opcache导致php-fpm崩溃nginx返回502
Mar 02 PHP
php字符串函数学习之strstr()
Mar 27 PHP
PHP在同一域名下两个不同的项目做独立登录机制详解
Sep 22 PHP
Phpstorm+Xdebug断点调试PHP的方法
May 14 PHP
PHP中数组转换为SimpleXML教程
Jan 27 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
Windows下IIS6/Apache2.2.4+MySQL5.2+PHP5.2.1安装配置方法
2007/05/03 PHP
php的字符串用法小结
2010/06/08 PHP
zend framework多模块多布局配置
2011/02/26 PHP
destoon文章模块调用企业会员资料的方法
2014/08/22 PHP
基于jQuery的图片大小自动适应实现代码
2010/11/17 Javascript
用Mootools获得操作索引的两种方法分享
2011/12/12 Javascript
jQuery的3种请求方式$.post,$.get,$.getJSON
2014/03/28 Javascript
jquery实现在光标位置插入内容的方法
2015/02/05 Javascript
jQuery检测返回值的数据类型
2015/07/13 Javascript
JavaScript获取当前cpu使用率的方法
2015/12/15 Javascript
Javascript如何判断数据类型和数组类型
2016/06/22 Javascript
浅谈jQuery效果函数
2016/09/16 Javascript
Bootstrap 模态框实例插件案例分析
2016/12/28 Javascript
简单实现js无缝滚动效果
2017/02/05 Javascript
vue 组件使用中的一些细节点
2018/04/25 Javascript
vue里面v-bind和Props 利用props绑定动态数据的方法
2018/08/27 Javascript
Vue keepAlive 数据缓存工具实现返回上一个页面浏览的位置
2019/05/10 Javascript
Angular5整合富文本编辑器TinyMCE的方法(汉化+上传)
2020/05/26 Javascript
Python将多个excel表格合并为一个表格
2021/02/22 Python
python在TXT文件中按照某一字符串取出该字符串所在的行方法
2018/12/10 Python
不归路系列:Python入门之旅-一定要注意缩进!!!(推荐)
2019/04/16 Python
500行Python代码打造刷脸考勤系统
2019/06/03 Python
python文件转为exe文件的方法及用法详解
2019/07/08 Python
使用pyqt5 tablewidget 单元格设置正则表达式
2019/12/13 Python
使用OpenCV对车道进行实时检测的实现示例代码
2020/06/19 Python
Python lxml库的简单介绍及基本使用讲解
2020/12/22 Python
波兰最大的宠物用品网上商店:FERA.PL
2019/08/11 全球购物
毕业生个人求职的自我评价
2013/10/28 职场文书
竞争上岗实施方案
2014/03/21 职场文书
《花木兰》教学反思
2014/04/09 职场文书
安全生产宣传标语
2014/06/06 职场文书
采购部长岗位职责
2014/06/13 职场文书
二手车交易协议书标准版
2014/11/16 职场文书
2014年人事科工作总结
2014/11/19 职场文书
django学习之ajax post传参的2种格式实例
2021/05/14 Python
Java面试题冲刺第十六天--消息队列
2021/08/07 面试题