• SPL接口学习总结


    迭代器接口描述(接口在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 . '
    ';
    $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 . '
    ';
    	}
    }
    
    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 . '
    ';
    $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);
    
  • 相关阅读:
    ubuntu配置jdk和tomcat+部署java项目[最佳实践]
    jQuery TreeGrid
    关于json的一些误解
    jQuery2.0.3源码分析-1(持续更新中......)
    webstrom一些常用快捷键
    js插件-Map插件
    webstorm-删除项目
    随笔-20131209
    软件开发模式对比(瀑布、迭代、螺旋、敏捷)
    javascript学习(10)——[知识储备]链式调用
  • 原文地址:https://www.cnblogs.com/chenqionghe/p/4551025.html
Copyright © 2020-2023  润新知