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
PHP 网络开发详解之远程文件包含漏洞
Apr 25 PHP
PHP中冒号、endif、endwhile、endfor使用介绍
Apr 28 PHP
php jquery 多文件上传简单实例
Dec 23 PHP
PHP中feof()函数实例测试
Aug 23 PHP
PHP将字符分解为多个字符串的方法
Nov 22 PHP
ThinkPHP通过AJAX返回JSON的两种实现方法
Dec 18 PHP
thinkphp多层MVC用法分析
Dec 30 PHP
如何使用php等比例缩放图片
Oct 12 PHP
PhpStorm配置Xdebug调试的方法步骤
Feb 02 PHP
PHP+Oracle本地开发环境搭建方法详解
Apr 01 PHP
php中钩子(hook)的原理与简单应用demo示例
Sep 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使用Jpgraph绘制复杂X-Y坐标图的方法
2015/06/10 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
2017/09/21 PHP
PHP连接MySQL数据库三种实现方法
2020/12/10 PHP
js 数组实现一个类似ruby的迭代器
2009/10/27 Javascript
JavaScript(JS) 压缩 / 混淆 / 格式化 批处理工具
2010/12/10 Javascript
深入理解JavaScript 闭包究竟是什么
2013/04/12 Javascript
阻止事件(取消浏览器对事件的默认行为并阻止其传播)
2013/11/03 Javascript
JQuery文字列表向上滚动的代码
2013/11/13 Javascript
教你如何在 Javascript 文件里使用 .Net MVC Razor 语法
2014/07/23 Javascript
JavaScript学习心得之概述
2015/01/20 Javascript
轻量级的原生js日历插件calendar.js使用指南
2015/04/28 Javascript
用JavaScript动态建立或增加CSS样式表的实现方法
2016/05/20 Javascript
jQuery实现倒计时(倒计时年月日可自己输入)
2016/12/02 Javascript
原生JS发送异步数据请求
2017/06/08 Javascript
layui实现三级导航菜单
2019/07/26 Javascript
django开发之settings.py中变量的全局引用详解
2017/03/29 Python
神经网络理论基础及Python实现详解
2017/12/15 Python
numpy中索引和切片详解
2017/12/15 Python
Python中的CSV文件使用"with"语句的方式详解
2018/10/16 Python
浅析Python与Mongodb数据库之间的操作方法
2019/07/01 Python
如何使用Python脚本实现文件拷贝
2019/11/20 Python
python中必要的名词解释
2019/11/20 Python
简单了解python数组的基本操作
2019/11/26 Python
python ImageDraw类实现几何图形的绘制与文字的绘制
2020/02/26 Python
Python 实现一行输入多个数字(用空格隔开)
2020/04/29 Python
Anaconda+vscode+pytorch环境搭建过程详解
2020/05/25 Python
Python小白学习爬虫常用请求报头
2020/06/03 Python
Keras 快速解决OOM超内存的问题
2020/06/11 Python
Python xpath表达式如何实现数据处理
2020/06/13 Python
html5自带表单验证体验优化及提示气泡修改功能
2017/09/12 HTML / CSS
html5写一个BUI折叠菜单插件的实现方法
2019/09/11 HTML / CSS
Probikekit欧盟:在线公路自行车专家
2019/07/12 全球购物
Maisons du Monde德国:法国家具和装饰的市场领导者
2019/07/26 全球购物
产品生产计划书
2014/05/07 职场文书
2016年全国助残日活动总结
2016/04/01 职场文书
解决Golang time.Parse和time.Format的时区问题
2021/04/29 Golang