vlambda博客
学习文章列表

PHP进阶教程-设计模式之单例模式

单例模式,属于创建类型的一种常用的软件设计模式。

通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)

对外提供全局实例的访问入口,它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。

结构图


主要解决的问题


保证一个类仅有一个实例,并提供一个访问它的全局访问点。避免一个全局使用的类频繁地创建与销毁。


优缺点

优点

  • 单例模式确保同一个进程中同一个对象只有一个实例,阻止其他对象直接new

  • 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。

  • 避免对资源的多重占用(比如写文件操作)。

缺点

  • 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

注意:

  • 单例类只能有一个实例。

  • 单例类必须自己创建自己的唯一实例。

  • 单例类必须给所有其他对象提供这一实例。

  • 单例类禁止被new,也禁止被clone

实现思路

  • 1、创建一个类,提供一个私有属性用来存储当前类对象实例。

  • 2、把构造方法设置为私有。

  • 3、如果是php语言编写把 __clone 方法设置为私有(其他语言忽略)。

  • 4、提供一个获取对象方法,在方法里面判断私有属性是否已经实例化成功,如果没有则new,如果有则返回。

示例代码:

Sunny.php

class Sunny{ private static $instance = null; private $name;
private function __construct(){ }
private function __clone(){ }
public static function getInstance(){ if (self::$instance == null) { self::$instance = new static(); } return self::$instance; }
/** * @return mixed */ public function getName(){ return $this->name; }
/** * @param mixed $name */ public function setName($name): void{ $this->name = $name; }}


代码调用:

$sunny = Sunny::getInstance();$sunny1 = Sunny::getInstance();$sunny->setName("sunny");echo $sunny->getName() . "\n";//输出sunnyecho $sunny1->getName()."\n";//输出sunnyvar_dump($sunny===$sunny1);//true

结果输出:

sunnysunnybool(true)

$sunny 的结果输出了 sunny ,$sunny1 并没有赋值但是也是得到了 sunny 结果,因为它们是同一个对象。

两个对象进行对比,它们也是等于 true 的,说明获取到的都是同一个对象。

如果觉得文章还不错,请把文章分享给更多的人学习,在文章中发现有误的地方也希望各位指出更正。现有误的地方也希望各位指出更正。