前言:这个章节主要分享一些高级的PHP面向对象的知识
(一) 两种常见的设计模式(单例和工厂模式)
引言:在PHP中,存在两种常见的设计模式,一个是单例模式,另一个是工厂模式,这两中设计模式,并不是固定的PHP语法,而是广大的开发工作者在长期的开发工作中总结出来的开发经验。
1.单例模式
<?php //单例模式实现的目标效果是: 无论我们实例化多少次,都只能得到唯一的一个对象(空间)。 class A{ private static $_obj;//定义了一个 静态的 私有的 属性 //将构造方法私有化,使得无法在类的外部使用new关键字实例化这个类的对象 private function __construct(){ } private function __clone(){ } //定义一个共有的 静态的 方法single public static function single(){ //判断$_obj静态私有属性是否保存了一个本类的对象 if( empty(self::$_obj) ){//如果$_obj为空,则表示之前没有创建过本类的对象 self::$_obj = new self; } return self::$_obj; } }
2.工厂模式
<?php class Factory{ public static function produce($className){ if( $className==‘A‘ ){ include ‘./A.class.php‘; }elseif( $className==‘B‘ ){ include ‘./B.class.php‘; } $obj = new $className; return $obj; } } $a1 = Factory::produce(‘A‘); var_dump( $a1 ); echo ‘<hr/>‘; $b1 = Factory::produce(‘B‘); var_dump( $b1 );
(二) 对象遍历
引言:对象和数组本质上同属于复合数据类型,我们可以在程序中可以对数组进行遍历。
1.默认的对象遍历
<?php class A{ public $name=‘zhangsan‘; public $age=12; public $height=1.8; } $a1 = new A; var_dump( $a1 ); echo ‘<hr/>‘;echo ‘<hr/>‘; //实现使用foreach对对象进行遍历 foreach( $a1 as $k=>$v ){ echo ‘$k:‘; var_dump( $k ); echo ‘<br/>‘; echo ‘$v:‘; var_dump( $v ); echo ‘<hr/>‘; }//小结:默认的对象遍历,就是逐个的获得对象中的属性(属性名和属性值);
2.自定义对象遍历
实现自定义对象遍历的前提:需要实现PHP预定义接口"Iterator"
自定义对象遍历的概念:当遍历一个对象时,PHP自动按顺序执行预定义接口Iterator中实现的五个方法。
<?php class A implements Iterator{ public $count=0; public function current(){ echo ‘current<br/>‘; } public function key(){ echo ‘key<br/>‘; } public function next(){ echo ‘next<br/>‘; } public function rewind(){ echo ‘rewind<br/>‘; } public function valid(){ $this->count++; if( $this->count<4 ){ echo ‘valid<br/>‘; return true; }else{ return false; } } } $a1 = new A; var_dump( $a1 ); echo ‘<hr/>‘; foreach( $a1 as $k=>$v ){ } 小结:
- 第一次将会按照 rewind->valid->current->key->next这个顺序执行五个被实现的方法;
- 第二次以后会按照 valid->current->key->next这个顺序循环执行4个被实现的方法;
(三) 对象序列化
在PHP中,如果我们直接将(PHP八种数据类型)数据写入文件中,那么,除了字符串数据外,其他的数据都将会失真。
概念:对象的序列化就是通过serialize函数将某个对象转换成一个具有固定信息格式的字符串。涉及的函数:serialize(对象) 将对象进行序列化
<?php class DirTool{ public $path; public $resource; public function __construct(){ $this->path = ‘./dir‘; $this->resource = opendir($this->path); } } $d = new DirTool; var_dump( $d ); echo ‘<hr/>‘; //将$d对象进行序列化,获得序列化之后的字符串结果 $str = serialize($d); var_dump( $str );
小结:
- 经过序列化之后的对象,变成了一个具有一定格式的字符串。
- 资源类型的数据即使序列化之后也会失真,所以一般我们在对对象进行序列化的时候,会把资源类型的数据排除在外;
2.__sleep魔术方法
<?php class DirTool{ public $path; public $resource; public function __construct(){ $this->path = ‘./dir‘; $this->resource = opendir($this->path); } //__sleep魔术方法 当基于该类的对象被序列化的时候,__sleep魔术方法将被触发执行 public function __sleep(){ //echo 100; return [‘path‘];//不在数组中的属性名,将会被排除在序列化操作之外 } } $d = new DirTool; var_dump( $d ); echo ‘<hr/>‘; //将$d对象进行序列化,获得序列化之后的字符串结果 $str = serialize($d); var_dump( $str );
小结:
- PHP不负责定义__sleep魔术方法,只负责调用该魔术方法;
- 调用该魔术方法的时机是:当使用serialize函数序列化一个对象时,该类中的__sleep魔术方法将会被触发自动执行;
- 在__sleep魔术方法中,可以同return语句指定乃个属性应该参与到序列化的过程中来,不在数组中的属性都将被排除在序列化的过程之外;
(四) 对象的反序列化
概念:对象的反序列化就是通过unserialize函数将某个对象序列化后的字符串还原回原来的对象。涉及的函数:unserialize(序列化后的字符串) 将对象进行反序列化
<?php $str = ‘O:7:"DirTool":2:{s:4:"path";s:5:"./dir";s:8:"resource";i:0;}‘; //将序列化后的字符串进行反序列化,还原回对象 $obj = unserialize($str); var_dump( $obj );
小结:我们从效果上看,虽然反序列化回了对象,但是找错了所属的类,这是因为在反序列化的过程中,需要有一个条件,那就是,必须存在这个对象的原始类的定义,即要在序列化的同一个php文件中进行
<?php class DirTool{ public $path; public $resource; public function __construct(){ $this->path = ‘./dir‘; $this->resource = opendir($this->path); } } $str = ‘O:7:"DirTool":2:{s:4:"path";s:5:"./dir";s:8:"resource";i:0;}‘; //将序列化后的字符串进行反序列化,还原回对象 $obj = unserialize($str); var_dump( $obj );
小结:
- 我们可以使用unserialize函数对序列化后的字符串结果进行反序列化;
- 反序列化有一个前提,在反序列化的过程中,必须存在该对象的原始类的定义,否则将会把还原的对象归到一个系统类__PHP_Incomplete_Class下;
<?php class DirTool{ public $path; public $resource; public function __construct(){ $this->path = ‘./dir‘; $this->resource = opendir($this->path); } //__wakeup魔术方法 public function __wakeup(){ $this->resource = opendir($this->path); } } //$str = ‘O:7:"DirTool":2:{s:4:"path";s:5:"./dir";s:8:"resource";i:0;}‘; $str = ‘O:7:"DirTool":1:{s:4:"path";s:5:"./dir";}‘; var_dump(unserialize($str));
小结:
- 我们在__wakeup魔术方法中所作的操作,其实就是将之前排除的属性重新进行赋值操作;
- PHP不负责定义__wakeup魔术方法,只负责调用该魔术方法;
- 调用该魔术方法的时机是:当使用unserialize函数反序列化一个字符串时,该类中的__wakeup魔术方法将会被触发自动执行;
(五) 命名空间
#关键字为namespace namespace 空间名; 注意事项:命名空间首次定义之前不能有任何PHP非注释代码;
命名空间的使用
<?php namespace first; function f1(){ echo 100; } namespace second; function f1($v1){ echo 200; } f1();//就近原则,不限定名称访问\first\f1();// 限定命名空间的访问 echo ‘嘿嘿嘿嘿,能看到我么‘;
命名空间的引入
//空间的引入,接上一个方法 use \first;f1();
小结 :
1.命名空间都是在全局空间下的
2.命名空间如果需要用到另外的空间需要用use引入才可以使用
原文地址:https://www.cnblogs.com/learningPHP-students2018/p/10201425.html