单例模式:使一个类只允许有一个对象的模式

实现方式

第一步:防止用户通过 new 关键字无限实例化新对象

new 一个对象的时候,会自动触发构造方法,只需要把这个构造方法私有化,类外就无
new 一个新的对象了

第二步:增加一个静态的公共方法,进入类的内部

  1. 为什么要静态?
    因为此时暂时还无法得到一个对象,只能通过类来访问这个方法
  2. 为什么是公共的?
    因为是类外访问!必须公开

    第三步:为当前类增加一个私有的静态属性

  3. 为什么是私有的?
    因为我们要确保在类外无法修改该属性的值!
  4. 为什么是静态的?
    因为此时需要使用类来调用这个属性!

    第四步:将克隆魔术方法私有化

    因为在克隆一个对象的时候,会自动触发执行__clone()魔术方法,只需要将方法同构造方法
    一样私有化即可

    code

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    <?php
    namespace Design\Singleton;

    final class Singleton
    {
    /**
    * @var Singleton 增加一个私有属性,用于保存对象
    */
    private static $instance;

    /**
    * 1.增加静态公开方法
    */
    public static function getInstance(): Singleton
    {
    if (!self::$instance instanceof self) {
    self::$instance = new self;
    }
    return self::$instance;
    }

    /**
    * 不允许从外部调用以防止创建多个实例
    * 要使用单例,必须通过 Singleton::getInstance() 方法获取实例
    */
    private function __construct()
    {
    }

    /**
    * 防止实例被克隆
    */
    private function __clone()
    {
    }

    /**
    * 防止反序列化
    */
    private function __wakeup()
    {
    }
    }

案例 MySQL 类的单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
namespace models;
use PDO;
final class MySQL
{
/**
* @var Singleton 增加一个私有属性,用于保存对象
*/
private static $instance;

/**
* 1.增加静态公开方法
*/
public static function getInstance()
{
if (!self::$instance instanceof self) {

self::$instance = new self();
}
return self::$instance;
}

/**
* 不允许从外部调用以防止创建多个实例
* 要使用单例,必须通过 Singleton::getInstance() 方法获取实例
*/

private function __construct()
{

$config = config('db');
self::$instance = new PDO('mysql:host=' . $config['host'] . ';dbname=' . $config['dbname'], $config['user'], $config['password']);
self::$instance->exec('SET NAMES ' . $config['charset']);
}

/**
* 防止实例被克隆
*/
private function __clone()
{
}

/**
* 防止反序列化
*/
private function __wakeup()
{
}
}

 评论


本站使用 Material X 作为主题 , 总访问量为 次 。
隐藏