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
无限级别菜单的实现
Oct 09 PHP
解析thinkphp中的M()与D()方法的区别
Jun 22 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
Nov 18 PHP
PHP实现事件机制实例分析
Jun 26 PHP
php图像处理类实例
Jul 28 PHP
php获取远程文件的内容和大小
Nov 03 PHP
Yii框架组件和事件行为管理详解
May 20 PHP
PHP对象克隆clone用法示例
Sep 28 PHP
php文件上传及下载附带显示文件及目录功能
Apr 27 PHP
PHPstorm快捷键(分享)
Jul 17 PHP
PHP添加文字水印或图片水印的水印类完整源代码与使用示例
Mar 18 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
用 PHP5 轻松解析 XML
2006/12/04 PHP
Yii Framework框架获取分类下面的所有子类方法
2014/06/20 PHP
thinkPHP内置字符串截取函数用法详解
2016/11/15 PHP
jquery ajax jsonp跨域调用实例代码
2013/12/11 Javascript
javascript生成json数据简单示例分享
2014/02/14 Javascript
详解AngularJS过滤器的使用
2016/03/11 Javascript
jQuery循环遍历子节点并获取值的方法
2016/04/14 Javascript
使用jQuery中的wrap()函数操作HTML元素的教程
2016/05/24 Javascript
微信+angularJS的SPA应用中用router进行页面跳转,jssdk校验失败问题解决
2016/09/09 Javascript
微信小程序 tabs选项卡效果的实现
2017/01/05 Javascript
backbone简介_动力节点Java学院整理
2017/07/14 Javascript
IScroll那些事_当内容不足时下拉刷新的解决方法
2017/07/18 Javascript
Vue网页html转换PDF(最低兼容ie10)的思路详解
2017/08/24 Javascript
基于vue-video-player自定义播放器的方法
2018/03/21 Javascript
vue移动端html5页面根据屏幕适配的四种解决方法
2018/10/19 Javascript
Vue.js@2.6.10更新内置错误处机制Fundebug同步支持相应错误监控
2019/05/13 Javascript
webpack4 SplitChunks实现代码分隔详解
2019/05/23 Javascript
vue实现滑动切换效果(仅在手机模式下可用)
2020/06/29 Javascript
Vue 权限控制的两种方法(路由验证)
2019/08/16 Javascript
js实现旋转木马轮播图效果
2020/01/10 Javascript
Vue proxyTable配置多个接口地址,解决跨域的问题
2020/09/11 Javascript
使用python编写android截屏脚本双击运行即可
2014/07/21 Python
python批量修改文件名的实现代码
2014/09/01 Python
python多重继承实例
2014/10/11 Python
Python的组合模式与责任链模式编程示例
2016/02/02 Python
详解supervisor使用教程
2017/11/21 Python
python pandas.DataFrame选取、修改数据最好用.loc,.iloc,.ix实现
2018/06/11 Python
Python坐标轴操作及设置代码实例
2020/06/04 Python
HTML5 Notification(桌面提醒)功能使用实例
2014/03/17 HTML / CSS
HTML5 canvas基本绘图之绘制线条
2016/06/27 HTML / CSS
专门出售各种儿童读物的网站:Put Me In The Story
2016/08/07 全球购物
金融管理毕业生求职信
2014/03/03 职场文书
2014年酒店工作总结范文
2014/11/17 职场文书
2015年小学数学教师工作总结
2015/05/20 职场文书
2015教师个人德育工作总结
2015/07/22 职场文书
浅谈MySQL之select优化方案
2021/08/07 MySQL