单例即一个类是能有一个实例,并提供一个当前类的全局唯一访问入口(getInstance)。防止类被多次实例化和clone,拥有单例带来好处的同时,也会失去在其他地方带来的不便。可能你们还是不懂,我就来举个发送邮件例子,smtp是可以设置自己账号作为发送邮件账号的,只需开启邮件密码就可以编写发送邮件代码,伪代码如下:
class Mail
{
private static $instance = null;
public function __construct(string $driver = 'smtp', array $config)
{
if (!isset(self::$instance[$driver])
self::$instance[$driver] = new self($driver, $config);
}
return self::$instance[$driver];
}
public function to(string $emai) {
// todo...
}
}
$senders = [
[
'driver' => 'smtp',
'name' => '小明',
'email' => 'xiaoming@qq.com',
'password' => '123456',
],
[
'driver' => 'smtp',
'name' => '小华',
'email' => 'xiiaohua@qq.com',
'password' => '123456',
]
];
foreach($senders as $sender) {
$mail = new Mail($sender['driver'],config('mail'));
$mail->to('wanger@qq.com')->send();
}
看到这样的代码就知道一眼看上了问题所在了吧,执行小明发送是没有问题的,但是轮到小华发送的时候其实延用了小明的smtp邮件发送。单例带来的不便就显现出来了吧。当然避开这个抗也是挺方便的,我们观察一下容易发现,其实是邮件的发送者不同,我们可以改造一下代码, 将配置文件作为参数传递,问题就得到解决:
class Mail
{
private static $instance = null;
public function __construct(string $driver = 'smtp')
{
if (!isset(self::$instance[$driver])
self::$instance[$driver] = new self($driver);
}
return self::$instance[$driver];
}
public function to(string $emai) {
// todo...
}
public function config(array $config) {
// todo...
}
}
// 调用就改为
foreach($senders as $sender) {
$mail = new Mail($sender['driver']);
$mail->config($send['config'])->to($send['mail'])->send();
}