本文同步更新於blog
情境:三只小猪想要盖房子
<?php
namespace App\PrototypePattern\Building;
class Wall
{
/**
* @var string
*/
public $material;
public function __construct(string $material)
{
$this->material = $material;
}
}
<?php
namespace App\PrototypePattern\Building;
use App\PrototypePattern\Building\Wall;
class Building
{
/**
* @var string
*/
public $name;
/**
* @var Wall
*/
public $wall;
/**
* @param Wall $wall
* @param string $name
*/
public function __construct(Wall $wall, string $name = 'unnamed')
{
$this->wall = $wall;
$this->name = $name;
}
}
<?php
namespace App\PrototypePattern\Building;
use App\PrototypePattern\Building\Building;
use App\PrototypePattern\Building\Wall;
class Program
{
/**
* @return array
*/
public function run()
{
//firstBuilding
$strawWall = new Wall('straw');
$firstBuilding = new Building($strawWall, 'oldestPigHouse');
dump($firstBuilding->name); // oldestPigHouse
dump($firstBuilding->wall->material); // straw
}
}
完成後,猪大哥很得意自己对房子的设计,
询问弟弟们要不要直接拷贝一间。
需求一:拷贝猪大哥的稻草屋
两个弟弟想了想,拷贝大哥的房子,好像是个省事的方法,
但二弟想用木材 (wood),三弟想用砖块 (bricks) 来盖房子。
<?php
namespace App\PrototypePattern\Building;
use App\PrototypePattern\Building\Building;
use App\PrototypePattern\Building\Wall;
class Program
{
/**
* @return array
*/
public function run()
{
//firstBuilding
$strawWall = new Wall('straw');
$firstBuilding = new Building($strawWall, 'oldestPigHouse');
//secondBuilding
$secondBuilding = clone $firstBuilding;
$secondBuilding->name = 'middlePigHouse';
$secondBuilding->wall->material = 'wood';
//thirdBuilding
$thirdBuilding = clone $firstBuilding;
$thirdBuilding->name = 'youngestPigHouse';
$thirdBuilding->wall->material = 'bricks';
dump($firstBuilding->name); // oldestPigHouse
dump($firstBuilding->wall->material); // bricks
dump($secondBuilding->name); // middlePigHouse
dump($secondBuilding->wall->material); // bricks
dump($thirdBuilding->name); // youngestPigHouse
dump($thirdBuilding->wall->material); // bricks
return [
'firstBuilding' => $firstBuilding,
'secondBuilding' => $secondBuilding,
'thirdBuilding' => $thirdBuilding
];
}
}
这时发生了件很尴尬的事情,
当猪二哥选用木材当建材时,大哥的稻草屋就变成木头屋了...
而猪小弟选用砖块当建材时,两个哥哥们的房子就变成砖头屋了...
导演表示,这样故事没办法进行下去,请我们修改一下。
需求二:让弟弟们对建材的修改,不会影响到哥哥
<?php
namespace App\PrototypePattern\Building;
use App\PrototypePattern\Building\Wall;
class Building
{
/**
* @var string
*/
public $name;
/**
* @var Wall
*/
public $wall;
/**
* @param Wall $wall
* @param string $name
*/
public function __construct(Wall $wall, string $name = 'unnamed')
{
$this->wall = $wall;
$this->name = $name;
}
public function __clone()
{
$this->wall = clone $this->wall;
}
}
<?php
namespace App\PrototypePattern\Building;
use App\PrototypePattern\Building\Building;
use App\PrototypePattern\Building\Wall;
class Program
{
/**
* @return array
*/
public function run()
{
//firstBuilding
$strawWall = new Wall('straw');
$firstBuilding = new Building($strawWall, 'oldestPigHouse');
//secondBuilding
$secondBuilding = clone $firstBuilding;
$secondBuilding->name = 'middlePigHouse';
$secondBuilding->wall->material = 'wood';
//thirdBuilding
$thirdBuilding = clone $firstBuilding;
$thirdBuilding->name = 'youngestPigHouse';
$thirdBuilding->wall->material = 'bricks';
dump($firstBuilding->name); // oldestPigHouse
dump($firstBuilding->wall->material); // straw
dump($secondBuilding->name); // middlePigHouse
dump($secondBuilding->wall->material); // wood
dump($thirdBuilding->name); // youngestPigHouse
dump($thirdBuilding->wall->material); // bricks
return [
'firstBuilding' => $firstBuilding,
'secondBuilding' => $secondBuilding,
'thirdBuilding' => $thirdBuilding
];
}
}
後来弟弟们改用其他建材时,就不会影响到原本哥哥的房子了。
这就是浅复制 (Shallow Copy) 与深复制 (Deep Copy) 的不同。
後来三只小猪跑去开建设公司,又是另一个故事了。
最後附上类别图:
(注:若不熟悉 UML 类别图,可参考UML类别图说明。)
ʕ •ᴥ•ʔ:一开始clone()方法能直接使用,是因为PHP的魔术方法__clone()唷!
>>: (33)试着学 Hexo-番外篇之更新 NexT 主题
此系列文章会同步发文到个人部落格,有兴趣的读者可以前往观看喔。 在浏览器上操作网页时,常常会开启新...
27. Remove Element 今天我们一起挑战leetcode第27题Remove Elem...
滚动组件-Sliver 若想要自定义滚动效果的介面功能,就需要使用 CustomScrollView...
接着来讲讲资料库连线的部分.... Mysql 类别Class public class Categ...
Chap.II Machine Learning 机器学习 https://yourfreetemp...