单例挖坑笔记

单例即一个类是能有一个实例,并提供一个当前类的全局唯一访问入口(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();
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2
fatrbaby

这不是单例的问题,这是抽象问题,职责没划分清楚。sendermaildriver耦合到一起了,当然会出现这样的问题。

1年前 评论

看完还是不懂

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!