您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息

每天一记之php原型模式

2024/4/27 6:05:04发布5次查看
每日一记之php原型模式
原型模式是指通过现有的实例通过拷贝得到新的实例。
在程序的设计中,有的时候我们去实例化某个对象需要做太多的初始化工作,非常耗时的时候,我们可以考虑采用原型模式来得到新的实例。
其实在php中我们很容易通过clone关键字去实现对象的复制。另外通过魔术方法__clone()指定在clone的时候需要进行的操作。这个其实就是原型模式的实现方式了。当然,有时候为了让代码看起来比较优雅,比较完善。我们可以自己去写相关的实现方式,当然也需要用到clone关键字。
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的效率以及具体讲解将在以后补充上
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录