单例挖坑笔记

PHP技术
456
0
0
2022-10-29

单例即一个类是能有一个实例,并提供一个当前类的全局唯一访问入口(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();
}