三月听我说

PHP原型模式

2018-09-23  本文已影响49人  三月孙记风
<?php
/*抽象原型类*/
abstract class Prototype {
    abstract function __clone();
}

class Map extends Prototype {
    public $width;
    public $height;
    public $sea;

    public function __conturct() {
        echo '我初始化了';
    }

    public function setAttribute(array $conllection) {
        foreach ($conllection as $key => $val) {
            $this->$key = $val;
        }
    }

    /*浅拷贝*/
    public function __clone() {}
    /*深度拷贝*/
    // public function __clone() {
    //  $this->sea = clone $this->sea;
    // }
    /**
     *推荐的深度拷贝
     * serialize() 返回字符串,此字符串包含了表示 value 的字节流,可以存储于任何地方。
     * 这有利于存储或传递 PHP 的值,同时不丢失其类型和结构。
     * unserialize() 对单一的已序列化的变量进行操作,将其转换回 PHP 的值。
     * */
    // public function __clone() {
    //  $serialize_obj = serialize($this->sea); //序列化
    //  $this->sea = unserialize($serialize_obj); //反序列化
    // }

}

class Sea {
    // public $fish;

    // public function __construct($fish) {
    //  $this->fish = $fish;
    // }
}


$map_protype = new Map();
$sttributes = array('width' => 40, 'height' => 60, 'sea' => (new Sea()));
$map_protype->setAttribute($sttributes);
$new_map = clone $map_protype;
var_dump($map_protype);
echo '<br>';
var_dump($new_map);

echo '<br>';
echo '<br>';
echo '<br>';
$new_map->width = 80;
var_dump($map_protype);
echo '<br>';
var_dump($new_map);

/*但是上面的代码还是存在一些问题。那就是它只是一个浅拷贝,
什么意思呢?map原型对象有一个属性sea存放了一个sea对象,
在调用setAttribute的时候,对象的赋值方式默认是引用。而当
我们克隆map对象时,直接克隆了map的sea属性,这就使得克
隆出来的对象与原型对象的sea属性对指向了,同一个sea对象
的内存空间。如果这个时候,我们改变了克隆对象的sea属性,
那么原型对象的sea属性也跟着改变*/
echo '<br>';
echo '<br>';
echo '<br>';
$new_map->sea->d = 80;
var_dump($map_protype);
echo '<br>';
var_dump($new_map);

$map_protype = new Map();
$sttributes = array('width' => 40, 'height' => 60, 'sea' => (new Sea('鱼')));
$map_protype->setAttribute($sttributes);
$new_map = clone $map_protype;
var_dump($map_protype);
var_dump($new_map);

$map_protype->sea->fish = "大鱼";
var_dump($map_protype);
echo '</br>';
var_dump($new_map);
上一篇 下一篇

猜你喜欢

热点阅读