php原型文档,每天一记之php原型模式

本文介绍了PHP中的原型模式,通过clone关键字实现对象的复制。详细阐述了如何通过__clone()方法在克隆时修改属性,以及浅克隆和深克隆的区别。在深克隆中,文章展示了如何处理对象内引用的其他对象,确保克隆后的对象独立。最后,提到了使用serialize和unserialize进行深克隆的一种方法。
摘要由CSDN通过智能技术生成

每日一记之php原型模式

原型模式是指通过现有的实例通过拷贝得到新的实例。

在程序的设计中,有的时候我们去实例化某个对象需要做太多的初始化工作,非常耗时的时候,我们可以考虑采用原型模式来得到新的实例。

其实在php中我们很容易通过clone关键字去实现对象的复制。另外通过魔术方法__clone()指定在clone的时候需要进行的操作。这个其实就是原型模式的实现方式了。当然,有时候为了让代码看起来比较优雅,比较完善。我们可以自己去写相关的实现方式,当然也需要用到clone关键字。

interface Cloneable{

public function copy();

}

class Task implements Cloneable{

public $name;

public $startTime;

public function __construct($name){

//这里实例化Task需要做很多工作

$this->name = $name;

$this->startTime = time();

}

public function copy(){

return clone $this;

}

}

在这里我们可以创建一个task

$task1 = new Task("Task1");

现在我们已经有了一个Task的实例了,我们要得到一个新的task实例就可以通过clone的方法

$task2 = $task1->copy();

可是现在这样我们打印$task1和$task2的startTime,两者是一样的,而我们又希望clone出来的对象时间应该是当前时间,怎么做呢?所以我们就得去写__clone方法,该方法在一个对象尝试进行clone的时候会自动调用。改良后的代码如下

class Task implements Cloneable{

public $name;

public $startTime;

public function __construct($name){

//这里实例化Task需要做很多工作

$this->name = $name;

$this->startTime = time();

}

public function __clone(){

//在克隆的时候把startTime设为当前时间

$this->startTime = time();

//克隆的时候需要执行的操作

}

public function copy(){

return clone $this;

}

}

这样克隆出来的对象的startTime就更正为当前时间了。

当然了,这只是一个简单的原型模式,在实际的克隆中,又分为浅克隆和深克隆。

浅克隆: 即对象在调用clone方法时只克隆基本的数据类型,而如果对象中包含其他对象的引用时,则copy其他对象的引用

深克隆:即除了克隆基本的数据类型外,引用的类型的数据也一并克隆。

举个例子,现在我的task类里面有一个其他对象的引用,比如Parent。相关代码如下:

class TaskParent{

public $name;

public function __construct($name){

$this->name = $name;

}

}

class Task implements Cloneable{

public $name;

public $startTime;

public $parent;

public function __construct($name){

//这里实例化Task需要做很多工作

$this->name = $name;

$this->startTime = time();

//这里直接new一个parent

$this->parent = new TaskParent("do some work");

}

public function __clone(){

//在克隆的时候把startTime设为当前时间

$this->startTime = time();

//克隆的时候需要执行的操作

}

public function copy(){

return clone $this;

}

}

在上面的代码里,我们新定义了一个TaskParent的类,然后Task持有该对象的一个引用,客户端代码:

$task1 = new Task("Task1");

echo $task1->parent->name."\r\n";

//clone一个对象

$task2 = $task1->copy();

echo $task2->parent->name."\r\n";

//将task1的parent的name设为另外的值

$task1->parent->name = "do another work";

//打印task2的parent的值

echo $task2->parent->name;

上面的代码最后一句话将打印 do another work,也就是说我们更改task1的parent影响到了task2。这就是典型的浅克隆,如果想实现深克隆,则可以进行如下改装

class Task implements Cloneable{

public $name;

public $startTime;

public $parent;

public function __construct($name){

//这里实例化Task需要做很多工作

$this->name = $name;

$this->startTime = time();

//这里直接new一个parent

$this->parent = new TaskParent("do some work");

}

public function __clone(){

//在克隆的时候把startTime设为当前时间

$this->startTime = time();

//克隆parent

$this->parent = clone $this->parent;

//克隆的时候需要执行的操作

}

public function copy(){

return clone $this;

}

}

我们在__clone方法里面对parent也进行了一次克隆,所以现在打印刚才的代码就没有问题了。这就是深克隆。

在真实的编码环境中,可能一个对象持有很多其他的对象的引用,而其他对象对象又持有很多的引用。由于引用的不确定性,我们一开始的时候就应该注意,到底哪些对象需要深克隆,那些对象不需要。

如果想实现快速的深克隆,网上一哥们提供了一个简单的方法代码如下:

class Task implements Cloneable{

public $name;

public $startTime;

public $parent;

public function __construct($name){

//这里实例化Task需要做很多工作

$this->name = $name;

$this->startTime = time();

//这里直接new一个parent

$this->parent = new TaskParent("do some work");

}

public function __clone(){

//在克隆的时候把startTime设为当前时间

$this->startTime = time();

//克隆parent

$this->parent = clone $this->parent;

//克隆的时候需要执行的操作

}

public function copy(){

//return clone $this;

//这里不使用clone关键字,而是使用序列化和反序列化来进行

return unserialize(serialize($this));

}

}

上述代码中通过serialize和unserialize来得到新的实例,经测试,完全是深克隆。关于serialize和unserialize的效率以及具体讲解将在以后补充上

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值