迭代器接口描述(接口在C里定义,这只是描述)

interface Iterator
{
public function current();
public function key();
public function next();
public function rewind();
}
//迭代器辅助函数
function print_entry($iterator)
{
print($iterator->current());
return true;
} $array = array(1,2,3);
$iterator = new ArrayIterator($array);
iterator_apply($iterator, 'print_entry',array($iterator)); //相当于array_walk

观察者模式

观察者模式:允许某个类观察另外一个类的状态,当被观察的类的状态发生变化时, 这个模式会得到通知
被观察的类叫subject,负责观察的类叫做observer
SPL提供了SplSubject和SplObserver接口

SplSubject 接口
interface SplSubject
{
public function attach(SplObserver $observer);
public function detach(SplObserver $observer);
public function notify();
}
SplObserver 接口
interface SplObserver
{
public function update(SplObserver $subject);
}
//被观察者
class DemoSubject implements SplSubject
{
private $observers, $value;
public function __construct()
{
$this->observers = array();
} public function attach(SplObserver $observer)
{
$this->observers[] = $observer;
} public function detach(SplObserver $observer)
{
if($idx = array_search($observer, $this->observers))
{
unset($this->observers[$idx]);
}
} public function notify()
{
foreach ($this->observers as $observer)
{
$observer->update($this);
}
} public function setValue($value)
{
$this->value = $value;
$this->notify();
} public function getValue()
{
return $this->value;
}
}
//观察者
class DemoObserver implements SplObserver
{
public function update(SplSubject $subject)
{
echo 'The new value is ' . $subject->getValue();
}
} $subject = new DemoSubject();
$observer = new DemoObserver();
$subject->attach($observer);
$subject->setValue('hello,world');

更好的观察者模式

观察模式的优点在于,挂接到订阅者上的观察者可多可少,并且不需要提前知道哪个类会响应subject类发出的事件
PHP6提供了SplObjectStorage类,这个类提升了观察者模式的可用性.这个类与数组相似,但它只能存储唯一性的对象,而且只存储这些对象的引用.这种做法有几个好处.
现在不能挂接一个类两次,可以防止多交代调用同一个对象的update()方法,而且,不需要迭代访问或者搜索集合,就可以从集合中删除某个对象,这提高了效率

//被观察者
class DemoSubject implements SplSubject
{
private $observers, $value;
public function __construct()
{
$this->observers = new SplObjectStorage();
}
public function attach(SplObserver $observer)
{
$this->observers->attach($observer);
}
public function detach(SplObserver $observer)
{
$this->observers->detach($observer);
}
public function notify()
{
foreach($this->observers as $observer)
{
$this->observers->update($this);
}
}
public function setValue($value)
{
$this->value = $value;
$this->notify();
}
public function getValue()
{
return $this->value;
}
}
//观察者
class DemoObserver implements SplObserver
{
public function update(SplSubject $subject)
{
echo 'The new value is ' . $subject->getValue();
}
}
$subject = new DemoSubject();
$observer = new DemoObserver();
$subject->attach($observer);
$subject->attach($observer);
$subject->setValue('hello,world');

序列化

SPL的Serializable接口为一些高级的序列化场景提供了支持,非SPL的序列化魔术方法的__sleep和__wakeup有一些问题,这些问题在SPL接口中都得到了解决
魔术方法不能序列化基类的私有变量.实现的__sleep函数必须返回变量名称的一个数组,并且要包含在序列化输出结果中,由于序列化发生的程序中,基类的私有成员的访问受到了限制.
通过允许调用父类的serialize()方法, Serializable接口消除了这一限制,父类的serialize()方法可以返回父类中序列化后的私有成员.

//魔术方法的序列化技术
error_reporting(E_ALL); //显示错误通知 class Base
{
private $baseVar;
public function __construct()
{
$this->baseVar = 'foo';
}
} class Extender extends Base
{
private $extendVar;
public function __construct()
{
parent::__construct();
$this->extendVar = 'bar';
}
public function __sleep()
{
return array('extenderVar','baseVar');
}
} $instance = new Extender();
$serialized = serialize($instance);
echo $serialized . '\n';
$restored = unserialize($serialized);

序列化对象(包含私有属性)

Serializable接口:
当实现 Serialize()方法,要求返回代表这个对象的序列化以后的字符,这个字符串通常是通过调用 serialize()方法获得的
unserialize()方法允许重新构造对象,它接受序列化的字符串作为输入.

interface Iterator
{
public function serialize();
public function unserialize($serialized);
}
error_reporting(E_ALL);	//显示错误通知

class Base implements Serializable
{
private $baseVar;
public function __construct()
{
$this->baseVar = 'foo';
} public function serialize()
{
return serialize($this->baseVar);
} public function unserialize($serialized)
{
$this->baseVar = unserialize($serialized);
} public function printMe()
{
echo $this->baseVar . '\n';
}
} class Extender extends Base
{
private $extendVar;
public function __construct()
{
parent::__construct();
$this->extendVar = 'bar';
}
public function serialize()
{
$baseSerialized = parent::serialize();
return serialize(array($this->extendVar,$baseSerialized));
} public function unserialize($serialized)
{
$temp = unserialize($serialized);
$this->extendVar = $temp[0];
parent::unserialize($temp[1]);
}
} $instance = new Extender();
$serialized = serialize($instance);
echo $serialized . '\n';
$restored = unserialize($serialized);
$restored->printMe();

SPL自动加载

安全的类加载方法

if(spl_autoload_call($class_name) && class_exists('className',false))
{
echo 'className was loaded';
//安全的实例化className类
$instance = new className;
}
else
{
//在这里实例化className类是不安全的
echo 'className was not found';
}

为对象设置一个独一无二的代码

class a{}
$instance = new a();
$reference = $instance;
echo spl_object_hash($instance) . PHP_EOL;
echo spl_object_hash($reference);

IteratorAggregate接口

IteratorAggregate接口是用来将Iterator接口要求实现的5个迭代器方法委托给其他类的.
这让你可以在类的外部实现迭代功能,并允许重新使用常用的迭代器方法,而不是在编写的每个可迭代类中重复使用这些方法

class MyIterableClass implements IteratorAggregate
{
protected $arr;
public function __construct()
{
$this->arr = array(1,2,3);
}
public function getIterator()
{
return new ArrayIterator($this->arr);
}
} //foreach循环遍历一个类
foreach(new MyIterableClass() as $value)
{
echo $value . PHP_EOL;
}

数组迭代器

数组迭代器实现SQL的LIMIT子句和OFFSET子句相同的迭代访问功能

$arr = array('a','b','c','e','f','g','h','i','j','k');
$arrIterator = new ArrayIterator($arr);
$limitIterator = new LimitIterator($arrIterator, 3, 4);
foreach($limitIterator as $v)
{
echo $v;
}

在一个循环中抚今追昔访问两个或多个数组

$arrFirst = new ArrayIterator(array(1,2,3));
$arrSecond = new ArrayIterator(array(4,5,6));
$iterator = new AppendIterator();
$iterator->append($arrFirst);
$iterator->append($arrSecond);
foreach($iterator as $v)
{
echo $v;
}

高级的数组合并功能
使用LimitIterator迭代器,AppendIterator迭代器和iterator_to_array()函数创建一个包含了每个输入数组前两元素的数组

$arrFirst = new ArrayIterator(array(1,2,3));
$arrSecond = new ArrayIterator(array(4,5,6));
$iterator = new AppendIterator();
$iterator->append(new LimitIterator($arrFirst, 0, 2));
$iterator->append(new LimitIterator($arrSecond, 0, 2));
print_r(iterator_to_array($iterator,false));

过滤数组接口FilterIterator

class GreaterThanThreeFilterIterator extends FilterIterator
{
public function accept()
{
return ($this->current() > 3);
}
}
$arr = new ArrayIterator(array(1,2,3,4,5,6,7,8));
$iterator = new GreaterThanThreeFilterIterator($arr);
print_r(iterator_to_array($iterator));

正则过滤数组接口regexIterator从FilterIterator类继承而来,允许使用几种正则表达式模式来匹配那些键值

$arr = array('apple','avocado','orange','pineapple');
$arrIterator = new ArrayIterator($arr);
$iterator = new RegexIterator($arrIterator, '/^a/');
print_r(iterator_to_array($iterator));

递归数组接口RecursiveArrayIterator,RecursiveIteratorIterator

$arr = array(
0 => 'a',
1 => array('a','b','c'),
2 => 'b',
3 => array('a','b','c'),
4 => 'c'
);
$arrayIterator = new RecursiveArrayIterator($arr);
$it = new RecursiveIteratorIterator($arrayIterator);
print_r(iterator_to_array($it,false));

数组重载

ArrayAccess接口:允许使用[]数组语法访问数据
使用ArrayAccess接口使对象的行为看起来和数组一样,包含四个方法

interface Iterator
{
public function offsetExistsw($offset);
public function offsetSet($offset,$value);
public function offsetGet($offset);
public function offsetUnSet($offset);
}
class MyArray implements ArrayAccess
{
protected $_arr;
public function __construct()
{
$this->_arr = array();
} public function offsetSet($offset, $value)
{
$this->_arr[$offset] = $value;
} public function offsetGet($offset)
{
return $this->_arr[$offset];
} public function offsetExists($offset)
{
return array_key_exists($offset, $this->_arr);
} public function offsetUnset($offset)
{
unset($this->_arr[$offset]);
} }
$myArray = new MyArray(); //创建可作为数组使用的对象
$myArray['first'] = 'test'; //offsetSet,通过键值设置数据
$demo = $myArray['first']; //offsetGet,通过键值获得数据
unset($myArray['first']); //offsetUnset,移除键值

ArrayObject类是一个ArrayAccess接口的实现类,它还提供了迭代功能,以及很多用来排序和处理数据的非常有用的方法

$myArray = new ArrayObject();
$myArray['first'] = 'first';
$myArray['second'] = 'second';
$myArray['third'] = 'third'; $demo = $myArray['first'];
unset($myArray['first']);
$numElements = count($myArray);
foreach($myArray as $key=>$value)
{
echo $value . PHP_EOL;
}
var_dump($myArray);

SPL接口学习总结的更多相关文章

  1. C# 常用接口学习 ICollection<T>

    C# 常用接口学习 ICollection<T> 作者:乌龙哈里 时间:2015-11-01 平台:Window7 64bit,Visual Studio Community 2015 参 ...

  2. C# 常用接口学习 IComparable 和 IComparer

    C# 常用接口学习 IComparable 和 IComparer 作者:乌龙哈里 时间:2015-11-01 平台:Window7 64bit,Visual Studio Community 201 ...

  3. 工程化编程实战callback接口学习笔记

    一.编译并运行 help.version命令执行正常,但quit命令出错 二.Debug 从命令输入到执行过程: 源代码: 更改后: 运行结果:能正确运行quit命令 Callback接口学习成果: ...

  4. caffe的python接口学习(1):生成配置文件

    caffe是C++语言写的,可能很多人不太熟悉,因此想用更简单的脚本语言来实现.caffe提供matlab接口和python接口,这两种语言就非常简单,而且非常容易进行可视化,使得学习更加快速,理解更 ...

  5. PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [3] 首页 APP 接口开发方案 ② 读取缓存方式

    以静态缓存为例. 修改 file.php line:11 去掉 path 参数(方便),加上缓存时间参数: public function cacheData($k,$v = '',$cacheTim ...

  6. OpenCV(C++接口)学习笔记1-图像读取、显示、保存

    OpenCV在2.0加入版本号之后C++接口函数,学习前C语言的接口功能.现在OpenCV它已被发展到2.4.9版本号,所以,我决定学习C++接口函数,与步伐. 1.创建图像 cv::Mat imag ...

  7. C# 常用接口学习 IEnumerable<T>

    作者:乌龙哈里 时间:2015-10-24 平台:Window7 64bit,Visual Studio Community 2015 本文参考: MSDN IEnumerable<T> ...

  8. java Thread 接口学习

    对于程序员来说 Thread应该都不会陌生,具体的接口调用不是本篇的重点.Thread的基本概念及接口的使用:java多线程 下面将更多的从底层实现角度讲一下Thread. Thread的声明如下: ...

  9. JDBC 接口学习

    说明:文章所有内容皆选自实验楼教程[JDBC 入门教程],想要学习更多JDBC,可以点击教程进行学习~ JDBC 简介 JDBC 的全称是 Java Database Connectivity,叫做 ...

随机推荐

  1. 手机服务器微架构设计与实现 之 http server

    手机服务器微架构设计与实现 之 http server ·应用 ·传输协议和应用层协议概念 TCP  UDP  TCP和UDP选择 三次握手(客户端与服务器端建立连接)/四次挥手(断开连接)过程图 · ...

  2. Vc 检测内存泄漏

    启用内存泄漏检测 检测内存泄漏是 C/c + + 调试器和 C 运行时库 (CRT) 的主要工具调试堆函数. 若要启用调试堆的所有函数,在 c + + 程序中,按以下顺序包含以下语句: C++复制 # ...

  3. Netsharp总体介绍

    作者:秋时   日期:2014年02月05日   转载须说明出处  Netsharp交流群:338963050(请有详细的请求说明) Netsharp系列文章目录结构 Netsharp是一款免费的基于 ...

  4. Spring Boot学习笔记:整合H2数据库

    H2数据库:java语言编写的嵌入式sql数据库.可以和应用一起打包发布. H2有三种连接模式(Connection Modes): Embedded mode (local connections ...

  5. Linux 第十三天

    十五.shell编程 1.Shell是什么 1)Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动.挂起.停止甚至是编写一 ...

  6. Eclipse进行远程调试(Tomcat远程调试)

    1.配置tomcat Linxu系统: tomcat/bin/catalina.sh或者startup.sh开始处中增加如下内容: declare -x CATALINA_OPTS="-Xd ...

  7. POJ3204 Ikki's Story I - Road Reconstruction

    Ikki's Story I - Road Reconstruction Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 7 ...

  8. 关不掉的小姐姐程序python tkinter实现 学习---打包教程

    首先,我们先准备两个.py文件,还要图片文件         代码//是我自己手写的,copy时记得删掉,不然有可能错误,比如中英文啥的    当然 一些语法的无问题就百度,都能给你答案 第一个.py ...

  9. Android中的EventBus

    1.分析 EventBus是一个针对Android的事件发布和订阅的框架,主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传 ...

  10. 源设置导致Docker镜像构建失败

    编写了一个Dockerfile,主要目的是构建一个镜像,镜像默认安装了openjdk-1.8-jre,还有另外一些包(这些包里面有dev版本的,也有release版本的),Dockerfile的内容大 ...