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 . '\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);

你可能感兴趣的:(接口)