[关闭]
@Chiang 2019-12-30T16:15:18.000000Z 字数 3601 阅读 495

创建型--单例模式(单一的实例)

设计模式


  • 单例模式是设计模式中最简单的形式之一,我们首先来了解一下PHP如何实现单例模式,三私一公是什么鬼?四私一公又是什么鬼?
  • 常用实例有MySQL的DB类

访问控制修饰符

  • public 公共的,当前类内,继承链类内和类外都可以访问
  • proteced 受保护的,当前类内以及继承链上的类内可以被访问到
  • private 私有的,只有当前类内可以被访问到

实现步骤

1.防止用户通过new关键字无限实例化新对象

私有化构造方法

  1. <?php
  2. /**
  3. * User: lufei
  4. * Date: 2019/9/12
  5. * Email: lufei@swoole.com
  6. */
  7. namespace Luffy\DesignPatterns\Singleton;
  8. /**
  9. * Class MySQLDB
  10. * @package Luffy\DesignPatterns\Singleton
  11. */
  12. class MySQLDB
  13. {
  14. /**
  15. * 1. 私有化构造方法 防止使用 new 创建多个实例
  16. * MySQLDB constructor.
  17. */
  18. private function __construct()
  19. {
  20. }
  21. }
  22. $db1 = new MySQLDB();
  23. $db2 = new MySQLDB();
  24. var_dump($db1,$db2);

2.增加一个静态的公共方法,进入类的内部

  • 静态? 没有办法得到一个对象(私有化了构造方法,没有办法实例化一个对象),只能通过类来访问方法
  • 公共? 类外访问
  1. <?php
  2. /**
  3. * User: lufei
  4. * Date: 2019/9/12
  5. * Email: lufei@swoole.com
  6. */
  7. namespace Luffy\DesignPatterns\Singleton;
  8. /**
  9. * Class MySQLDB
  10. * @package Luffy\DesignPatterns\Singleton
  11. */
  12. class MySQLDB
  13. {
  14. /**
  15. * 2. 增加静态公共方法
  16. */
  17. public static function getInstance()
  18. {
  19. // 返回一个新对象
  20. return new self;
  21. }
  22. /**
  23. * 1. 私有化构造方法 防止使用 new 创建多个实例
  24. * MySQLDB constructor.
  25. */
  26. private function __construct()
  27. {
  28. }
  29. }
  30. // 如果想得到一个对象,就必须通过类名调用getInstance静态方法
  31. $db1 = MySQLDB::getInstance();
  32. // 反复调用 依旧创建多个对象
  33. $db2 = MySQLDB::getInstance();
  34. var_dump($db1, $db2);

3.增加一个私有的静态属性

实现对象单一性

  1. <?php
  2. /**
  3. * User: lufei
  4. * Date: 2019/9/12
  5. * Email: lufei@swoole.com
  6. */
  7. namespace Luffy\DesignPatterns\Singleton;
  8. /**
  9. * Class MySQLDB
  10. * @package Luffy\DesignPatterns\Singleton
  11. */
  12. class MySQLDB
  13. {
  14. /**
  15. * 增加私有的静态属性
  16. * @var
  17. */
  18. private static $instance;
  19. /**
  20. * 2. 增加静态公共方法
  21. */
  22. public static function getInstance()
  23. {
  24. /**
  25. * instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例
  26. * @link https://www.php.net/manual/zh/language.operators.type.php
  27. */
  28. if (!self::$instance instanceof self) {
  29. static::$instance = new self();
  30. }
  31. return static::$instance;
  32. }
  33. /**
  34. * 1. 私有化构造方法 防止使用 new 创建多个实例
  35. * MySQLDB constructor.
  36. */
  37. private function __construct()
  38. {
  39. }
  40. }
  41. // 如果想得到一个对象,就必须通过类名调用getInstance静态方法
  42. $db1 = MySQLDB::getInstance();
  43. $db2 = MySQLDB::getInstance();
  44. var_dump($db1, $db2);

4.将克隆魔术方法私有化

  • 私有化克隆方法
  • 阻止克隆获取新的对象
  1. <?php
  2. /**
  3. * User: lufei
  4. * Date: 2019/9/12
  5. * Email: lufei@swoole.com
  6. */
  7. namespace Luffy\DesignPatterns\Singleton;
  8. /**
  9. * Class MySQLDB
  10. * @package Luffy\DesignPatterns\Singleton
  11. */
  12. class MySQLDB
  13. {
  14. /**
  15. * 增加私有的静态属性
  16. * @var
  17. */
  18. private static $instance;
  19. /**
  20. * 2. 增加静态公共方法
  21. */
  22. public static function getInstance()
  23. {
  24. /**
  25. * instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例
  26. * @link https://www.php.net/manual/zh/language.operators.type.php
  27. */
  28. if (!self::$instance instanceof self) {
  29. static::$instance = new self();
  30. }
  31. return static::$instance;
  32. }
  33. /**
  34. * 1. 私有化构造方法 防止使用 new 创建多个实例
  35. * MySQLDB constructor.
  36. */
  37. private function __construct()
  38. {
  39. }
  40. // 4. 私有化__clone魔术方法
  41. private function __clone()
  42. {
  43. }
  44. }
  45. // 如果想得到一个对象,就必须通过类名调用getInstance静态方法
  46. $db1 = MySQLDB::getInstance();
  47. $db2 = MySQLDB::getInstance();
  48. var_dump($db1, $db2);

5.将__wakeup()方法私有化

反序列化的时候会重新加载对象

  1. <?php
  2. /**
  3. * User: lufei
  4. * Date: 2019/9/12
  5. * Email: lufei@swoole.com
  6. */
  7. namespace Luffy\DesignPatterns\Singleton;
  8. /**
  9. * Class MySQLDB
  10. * @package Luffy\DesignPatterns\Singleton
  11. */
  12. class MySQLDB
  13. {
  14. /**
  15. * 增加私有的静态属性
  16. * @var
  17. */
  18. private static $instance;
  19. /**
  20. * 2. 增加静态公共方法
  21. */
  22. public static function getInstance()
  23. {
  24. /**
  25. * instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例
  26. * @link https://www.php.net/manual/zh/language.operators.type.php
  27. */
  28. if (!self::$instance instanceof self) {
  29. static::$instance = new self();
  30. }
  31. return static::$instance;
  32. }
  33. /**
  34. * 1. 私有化构造方法 防止使用 new 创建多个实例
  35. * MySQLDB constructor.
  36. */
  37. private function __construct()
  38. {
  39. }
  40. // 4. 私有化__clone魔术方法
  41. private function __clone()
  42. {
  43. }
  44. //5.将__wakeup()方法私有化
  45. private function __wakeup()
  46. {
  47. // TODO: Implement __wakeup() method.
  48. }
  49. }
  50. // 如果想得到一个对象,就必须通过类名调用getInstance静态方法
  51. $db1 = MySQLDB::getInstance();
  52. $db2 = MySQLDB::getInstance();
  53. var_dump($db1, $db2);
  54. // 反序列化对象
  55. $db4 = unserialize(serialize($db1));
  56. var_dump($db4);

三私一公

  • 私有化构造方法: 防止使用new创建多个实例
  • 公共的静态方法: 进入类的内部
  • 私有化静态属性: 防止直接访问存储实例的属性
  • 私有化克隆方法: 防止克隆多个实例

四私一公

  • 私有化构造方法: 防止使用new创建多个实例
  • 公共的静态方法: 进入类的内部
  • 私有化静态属性: 防止直接访问存储实例的属性
  • 私有化克隆方法: 防止克隆多个实例
  • 私有化__wakeup()方法: 防止反序列

参考资料:
swoole微课堂
GitHub

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注