发邮件的功能想必都做过,发邮件相当的耗时,于是大多使用多线程来实现。但假设产生第一封邮件对象,放到线程1中运行,还没有发送出去,线程2也启动了,直接把邮件对象修改了,线程不安全了。在这里我使用原型模式来解决
class="php"><?php
class Mail{
private $title;
private $content;
private $receiver;
public function setTitle($title){
$this->title = $title;
}
public function getTitle(){
return $this->title;
}
public function setContent($content){
$this->content = $content;
}
public function getContent(){
return $this->content;
}
public function setReceiver($receiver){
$this->receiver = $receiver;
}
public function getReveiver(){
return $this->receiver;
}
public function sendMail(){
echo "内容为:".$this->content."的邮件已发送至".$this->receiver."\n";
}
}
$mail = new Mail();
$mail->setTitle('测试');
$i = 0;
while ($i<5) {//这里是例子,真实情况换为遍历用户
$cloneMail = clone $mail;//克隆一个邮件对象
$receiver = rand();
$cloneMail->setReceiver($receiver);
$cloneMail->setContent($receiver.'你好:......');
$cloneMail->sendMail();
$i++;
}
?>
运行结果:
内容为:32436你好:......的邮件已发送至32436
内容为:31453你好:......的邮件已发送至31453
内容为:22098你好:......的邮件已发送至22098
内容为:27939你好:......的邮件已发送至27939
内容为:21024你好:......的邮件已发送至21024
[Finished in 0.1s]
?通过克隆一个对象,可以将线程中的对象相隔离,因此互不影响。
?
?
原型模式的定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。太简单了,原型模式的核心是一个clone方法,通过该方法进行对象的拷贝,php5中提供了一个魔术方法__clone。
?
?
原型模式的优点
1、性能优良
原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点 。
2、逃避构造函数的约束
这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。优点就是减少了约束,缺点也是减少了约束,需要在实际应用中考虑
?
?
原型模式的使用场景
1、资源优化场景
类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等2
2、性能和安全要求的场景
通过new产生一个对象需要繁琐的数据准备或访问权限,则可以使用原型模式。
3、一个对象多个修改者的场景
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型式拷贝多个对象供调用者使用。
在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。
?
?
原型模式的注意事项
1、构造函数不会被执行
2、浅复制和深复制
使用clone来复制对象,这种复制叫做“浅复制”:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。也就是说,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。相对于浅复制,当然也有一个深复制:被复制的对象的所有的变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。也就是说,深复制把要复制的对象所引用的对象都复制了一遍。深复制需要决定深入到多少层,这是一个不容易确定的问题,此外可有会出现循环引用的问题,这些都必须小心处理。
3、clone和final两个冤家
尝试在类的一个成员变量加final,将会Cannot declare property Mail::$title final, the final modifier is allowed only for methods and classes这种类型的错误。要想使用clone方法,类的成员变量上不要增加final关键字。
?
?