PHP SPL標(biāo)準(zhǔn)庫(kù)之接口(Interface)詳解
PHP SPL標(biāo)準(zhǔn)庫(kù)總共有6個(gè)接口,如下:
1.Countable
2.OuterIterator
3.RecursiveIterator
4.SeekableIterator
5.SplObserver
6.SplSubject
其中OuterIterator、RecursiveIterator、SeekableIterator都是繼承Iterator類(lèi)的,下面會(huì)對(duì)每種接口作用和使用進(jìn)行詳細(xì)說(shuō)明。
Coutable接口:
實(shí)現(xiàn)Countable接口的對(duì)象可用于count()函數(shù)計(jì)數(shù)。
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
說(shuō)明:
調(diào)用count()函數(shù)時(shí),Mycount::count()方法被調(diào)用
count()函數(shù)的第二個(gè)參數(shù)將不會(huì)產(chǎn)生影響
OuterIterator接口:
自定義或修改迭代過(guò)程。
//IteratorIterator是OuterIterator的一個(gè)實(shí)現(xiàn)類(lèi)
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;
}
/*
結(jié)果:
0->bTEST
1->aTEST
2->cTEST
*/
在實(shí)際運(yùn)用中,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接口:
用于循環(huán)迭代多層結(jié)構(gòu)的數(shù)據(jù),RecursiveIterator另外提供了兩個(gè)方法:
RecursiveIterator::getChildren 獲取當(dāng)前元素下子迭代器
RecursiveIterator::hasChildren 判斷當(dāng)前元素下是否有迭代器
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;
}
}
/*
結(jié)果:
0
1 has children:
Array
(
[0] => 10
[1] => 20
)
2
3 has children:
Array
(
[0] => 1
[1] => 2
)
*/
SeekableIterator接口:
通過(guò)seek()方法實(shí)現(xiàn)可搜索的迭代器,用于搜索某個(gè)位置下的元素。
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 ();
}
/*
結(jié)果:
first element
third element
second element
invalid seek position ( 10 )
*/
SplObserver和SplSubject接口:
SplObserver和SplSubject接口用來(lái)實(shí)現(xiàn)觀察者設(shè)計(jì)模式,觀察者設(shè)計(jì)模式是指當(dāng)一個(gè)類(lèi)的狀態(tài)發(fā)生變化時(shí),依賴它的對(duì)象都會(huì)收到通知并更新。使用場(chǎng)景非常廣泛,比如說(shuō)當(dāng)一個(gè)事件發(fā)生后,需要更新多個(gè)邏輯操作,傳統(tǒng)方式是在事件添加后編寫(xiě)邏輯,這種代碼耦合并難以維護(hù),觀察者模式可實(shí)現(xiàn)低耦合的通知和更新機(jī)制。
看看SplObserver和SplSubject的接口結(jié)構(gòu):
//SplSubject結(jié)構(gòu) 被觀察的對(duì)象
interface SplSubject{
public function attach(SplObserver $observer); //添加觀察者
public function detach(SplObserver $observer); //剔除觀察者
public function notify(); //通知觀察者
}
//SplObserver結(jié)構(gòu) 代表觀察者
interface SplObserver{
public function update(SplSubject $subject); //更新操作
}
看下面一個(gè)實(shí)現(xiàn)觀察者的例子:
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();
/*
結(jié)果:
邏輯1代碼
邏輯2代碼
*/
相關(guān)文章
php用header函數(shù)實(shí)現(xiàn)301跳轉(zhuǎn)代碼實(shí)例
分享一個(gè)php 301跳轉(zhuǎn)的代碼,很簡(jiǎn)單,主要是用header函數(shù)實(shí)現(xiàn)轉(zhuǎn),大家可以參考使用2013-11-11根據(jù)ip調(diào)用新浪api獲取城市名并轉(zhuǎn)成拼音
這篇文章主要介紹了根據(jù)ip調(diào)用新浪api獲取城市名并轉(zhuǎn)成拼音的示例,,需要的朋友可以參考下2014-03-03PHP抓屏函數(shù)實(shí)現(xiàn)屏幕快照代碼分享
誰(shuí)說(shuō)抓圖只能用QQ、用打印屏幕,PHP也能做到,本文主要介紹PHP抓屏函數(shù)實(shí)現(xiàn)屏幕快照的方法2014-01-01使用laravel根據(jù)用戶類(lèi)型來(lái)顯示或隱藏字段
今天小編就為大家分享一篇使用laravel根據(jù)用戶類(lèi)型來(lái)顯示或隱藏字段,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10PHP array_reverse() 函數(shù)原理及實(shí)例解析
這篇文章主要介紹了PHP array_reverse() 函數(shù)原理及實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07