PHP的单例模式类写法

无意中看到一个所谓的"玩魔兽"学习PHP的设计模式的帖子,其中第一个就是所谓的"单价模式"(其实就是我们说的:Singleton class中文应该叫做'单例类').

 

名词解释:

Singleton_Class ['name' => '单例类'];

就是在整个程序运行生命周期内只能实例化一次的类.

 

PHP中的实现方法:(测试通过)

<?php
/**
 * 这是一个单例类,用来保存程序运行期间的数据.<br />
 * 这里体现了PHP的几个特殊的地方:
 * 1.构造函数可以用private,protected等限制访问符;
 * 2.在类的内部实例化自身,应该使用:new self(),而不是类的外部名称;
 *
 * @author Fonny
 *
 */
class SingletonModel
{
	private $_count_sm_instance = 0;
	/**
	 * SingletonModel的构造函数.<br />
	 * 可以加参数,但是同时也要在getInstance方法中添加同样的参数才能实现效果.
	 *
	 * @return SingletonModel
	 */
	private function __construct()
	{
		$this->_count_sm_instance++;
		$tl = new StudyTools();
		$tl->echoStr("SingletonModel instance count: " . $this->_count_sm_instance,false);
	}
	/**
	 * 仅子类可访问的本单例类的静态实例
	 * @var SingletonModel
	 */
	static protected $_instance = null;

	/**
	 * 获得SingletonModel类的全局唯一实例的唯一方法
	 *
	 * @return SingletonModel
	 */
	static public function getInstance()
	{
		if(self::$_instance === null)
		{
			self::$_instance = new self();
		}
		return self::$_instance;
	}
}
?>

 

<?php

require_once 'includes/singleton.class.php';

$sm = SingletonModel::getInstance();
$sm2 = SingletonModel::getInstance();

//只会得到同一个内存资源的引用
?>

 

 

 

<think>嗯,我现在要理解用户提供的这段PHP单例模式代码。首先,用户希望我解释这段代码的含义,可能他们刚开始学习设计模式,特别是单例模式。让我仔细看一下代码的结构和各个部分的作用。 首先,代码定义了一个名为Singleton的。里面有一个静态属性$_instance,被声明为private,这意味着它只能在内部访问。接下来是构造函数__construct()和克隆方法__clone(),它们都被设为private,这样外部就无法通过new或者clone来创建实例了。然后有一个公共的静态方法getInstance(),用于获取实例。这个方法内部有一个条件判断,检查self::$_instance是否是Singleton的实例。如果是,就创建一个新的实例并赋值给$_instance,最后返回这个实例。 不过,这里可能有问题。通常在单例模式中,我们是在实例不存在时才创建,而这里的条件判断看起来有问题。比如,当$_instance已经存在时,反而会去创建一个新实例,这显然不符合单例模式的要求。正确的做法应该是检查$_instance是否为null或者不是的实例,如果是的话才创建新实例。用户提供的代码中的条件判断可能写反了,导致每次调用getInstance()都会创建新实例,这实际上破坏了单例的特性。 接下来,我需要解释单例模式的基本概念:确保一个只有一个实例,并提供全局访问点。通常用于数据库连接、日志记录器等需要全局唯一实例的场景。然后指出代码中的构造函数和克隆方法被私有化,防止外部实例化,这是正确的步骤。但关键点在于getInstance()方法中的逻辑是否正确。 另外,注意到PHP中静态变量的作用域。在用户代码中,每次调用getInstance()时,instanceof检查可能总为false,导致每次都new一个实例,这样每次返回的都是新实例,而不是保持唯一。正确的条件应该是如果$_instance不存在,才创建。例如,应该用if (!self::$_instance instanceof self) 或者更简单的if (self::$_instance === null),然后进行实例化。 用户可能没有意识到这个错误,所以需要指出并给出正确的代码示例。同时,需要解释各个部分的作用,比如private构造和克隆方法的作用,以及静态方法如何控制实例的生成。 总结来说,这段代码意图是实现单例模式,但由于条件判断错误,导致无法正确实现单例。需要指出错误并提供修正后的代码,同时解释单例模式的各个组成部分。</think>好的,我来逐步解释这个单例模式的实现原理和存在问题: **单例模式核心思想**: 保证一个只能创建一个实例,并提供一个全局访问点(比如这里的`getInstance()`方法)。 **代码解析**: 1. **私有化构造函数** `private function __construct(){}` 禁止通过`new Singleton()`的方式创建实例,这是单例模式的基础保障 2. **禁止克隆** `private function __clone(){}` 防止通过`clone`方式复制对象,确保唯一性 3. **静态变量存储实例** `private static $_instance;` 级别的存储空间,用于保存唯一实例 4. **问题代码段**: ```php if(self::$_instance instanceof Singleton){ self::$_instance = new Singleton(); } ``` 这里存在逻辑错误:当实例已经存在时反而创建新对象,这会导致: - 第一次调用返回新实例 ✅ - 第二次调用会覆盖已有实例 ❌ - 后续每次调用都会创建新实例 ❌ **正确写法**应该判断实例是否不存在: ```php if (!self::$_instance instanceof self) { self::$_instance = new self(); } ``` **修正后的完整实现**: ```php class Singleton{ private static $_instance; private function __construct(){} private function __clone(){} public static function getInstance(){ if (!self::$_instance instanceof self) { self::$_instance = new self(); } return self::$_instance; } } ``` **使用示例**: ```php $instance1 = Singleton::getInstance(); $instance2 = Singleton::getInstance(); var_dump($instance1 === $instance2); // 输出 bool(true) ``` **应用场景**: 数据库连接器、日志记录器、配置管理器等需要全局唯一访问点的场景。 **关键点总结**: - 三私一公:私有构造方法、私有克隆方法、私有静态属性、公有静态获取方法 - 延迟初始化(Lazy Initialization) - 线程安全(在PHP中天然支持,因为PHP是单线程架构) 建议修正原代码中的判断条件,以真正实现单例模式的特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值