1. <?php
    2. class Singleton
    3. {
    4. /**
    5. * Singleton的实例存储在一个静态字段中。 该字段是一个数组,因为我们将让我们的Singleton具有子类。
    6. * 该数组中的每个项目都是特定Singleton子类的实例。 稍后您将了解其工作原理
    7. * @var array
    8. */
    9. private static $instances = [];
    10. /**
    11. * Singleton的构造函数应始终是私有的,以防止使用new运算符直接进行构造调用
    12. * Singleton constructor.
    13. */
    14. protected function __construct()
    15. {
    16. }
    17. /**
    18. * 单例不应该是可克隆的
    19. */
    20. protected function __clone()
    21. {
    22. }
    23. /**
    24. * 单例不应该从字符串中恢复 unserialize()调用抛出异常
    25. */
    26. public function __wakeup()
    27. {
    28. throw new \Exception("Cannot unserialize a singleton.");
    29. }
    30. /**
    31. * 这是控制对单例实例的访问的静态方法。 在第一次运行时,它将创建一个单例对象并将其放置到静态字段中。
    32. * 在随后的运行中,它返回存储在静态字段中的客户端现有对象。
    33. * 此实现使您可以在继承每个子类一个实例的同时,对Singleton类进行子类化
    34. * @return Singleton
    35. */
    36. public static function getInstance(): Singleton
    37. {
    38. $cls = static::class;
    39. if (!isset(self::$instances[$cls])) {
    40. self::$instances[$cls] = new static();
    41. var_dump(self::$instances);
    42. }
    43. return self::$instances[$cls];
    44. }
    45. /**
    46. * 任何单例都应该定义一些业务逻辑,这些逻辑可以在其实例上执行。
    47. */
    48. public function someBusinessLogic()
    49. {
    50. echo 'current class ' . static::class . PHP_EOL;
    51. }
    52. }
    53. $aa = Singleton::getInstance();
    54. $bb = Singleton::getInstance();
    55. var_dump($aa === $bb);
    56. $aa->someBusinessLogic();
    57. $bb->someBusinessLogic();
    58. class Db extends Singleton
    59. {
    60. }
    61. class RedisSingleton extends Singleton
    62. {
    63. }
    64. $db1 = Db::getInstance();
    65. $db2 = Db::getInstance();
    66. $db1->someBusinessLogic();
    67. $db2->someBusinessLogic();
    68. $redis1 = RedisSingleton::getInstance();
    69. $redis2 = RedisSingleton::getInstance();
    70. $redis1->someBusinessLogic();
    71. $redis2->someBusinessLogic();

    输出

    1. array(1) {
    2. ["Singleton"]=>
    3. object(Singleton)#1 (0) {
    4. }
    5. }
    6. bool(true)
    7. current class Singleton
    8. current class Singleton
    9. array(2) {
    10. ["Singleton"]=>
    11. object(Singleton)#1 (0) {
    12. }
    13. ["Db"]=>
    14. object(Db)#2 (0) {
    15. }
    16. }
    17. current class Db
    18. current class Db
    19. array(3) {
    20. ["Singleton"]=>
    21. object(Singleton)#1 (0) {
    22. }
    23. ["Db"]=>
    24. object(Db)#2 (0) {
    25. }
    26. ["RedisSingleton"]=>
    27. object(RedisSingleton)#3 (0) {
    28. }
    29. }
    30. current class RedisSingleton
    31. current class RedisSingleton