单例模式
<ul>
<li>确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。</li>
<li>被公认为是 反面模式,为了获得更好的可测试性和可维护性,请使用『依赖注入模式』。</li>
</ul>
<h3>目的</h3>
<ul>
<li>在应用程序调用的时候,只能获得一个对象实例。</li>
</ul>
<h3>为什么要使用单例模式</h3>
<ul>
<li>php的应用主要在于数据库应用, 一个应用中会存在大量数据库操作, </li>
<li>使用单例模式可以避免大量的new 操作消耗的资源,还可以减少数据库连接,这样就不容易出现 too many connections情况。</li>
<li>如果系统中需要有一个类来全局控制某些配置信息, 使用单例模式可以很方便实现。</li>
</ul>
<h3>单例模式的实现</h3>
<ul>
<li>三私一公:私有化静态属性,私有化构造方法,私有化克隆方法,公有化静态方法。</li>
<li>私有化一个属性用于存放唯一的一个实例</li>
<li>私有化构造方法,私有化克隆方法,用来创建并只允许创建一个实例</li>
<li>公有化静态方法,用于向系统提供这个实例</li>
</ul>
<h3>例子</h3>
<ul>
<li>数据库连接</li>
<li>日志 (多种不同用途的日志也可能会成为多例模式)</li>
<li>在应用中锁定文件 (系统中只存在一个 ...)</li>
</ul>
<h2>代码示例1</h2>
<pre><code class="language-PHP"><?php
/**
* 单例模式
*/
final class Singleton
{
/**
* @var Singleton
*/
private static $instance;
/**
* 通过懒加载获得实例(在第一次使用的时候创建)
*/
public static function getInstance(): Singleton
{
if (null === static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
/**
* 不允许从外部调用以防止创建多个实例
* 要使用单例,必须通过 Singleton::getInstance() 方法获取实例
*/
private function __construct()
{
}
/**
* 测试方法
*/
public function test()
{
echo '获取多例测试方法 <br />';
}
/**
* 防止实例被克隆(这会创建实例的副本)
*/
private function __clone()
{
}
/**
* 防止反序列化(这将创建它的副本)
*/
private function __wakeup()
{
}
}
// 单例初始化方法
$Singleton = Singleton::getInstance();
// 单例初调用方法
$Singleton->test();
</code></pre>
<h2>代码示例2</h2>
<pre><code class="language-PHP"><?php
header( 'Content-Type:text/html; charset=utf8;' );
//单例模式:一个类只能有一个实例对象存在.
/**场景:
多人协同开发,都要用到mysql类的实例,
如果用过svn,会知道,好多人一起开发,再提交各自的文件
A:
$mysql=new mysql();
$mysql->query();
//-->测试通过
B:
$db=new mysql();
//-->测试通过
…… 等多人
其中两人的代码要合到一块:
$mysql=new mysql();
$mysql->query();
$db=new mysql();
因此,
存在两个mysql类的实例,而且每new一下,还要连接一次数据库。
显然,
一个页面,有一个mysql类的实例就够了。
如何限制,让多人开发,无论你怎么操作,只能得到一个对象呢?
1-开会时经理说,有一个$db变量,是系统自动初始化的,就是mysql类的实例。
这是行政上的手段,不能阻止技术上的new mysql()行为。
2-技术上解决,单例模式
*/
/*
protected static $ins=null;
final protected function __construct(){
}
public static function getIns(){
if(self::$ins instanceof self){
return self::$ins;
}else{
self::$ins=new self();
return self::$ins;
}
}
*/
//单例模式
class Single{
public $hash;//随机码
static protected $ins=null;
final protected function __construct(){
$this->hash=mt_rand(1,999999);
}
static public function getInstance(){
//return new self();
if(self::$ins instanceof self){
return self::$ins;
}
self::$ins = new self();
return self::$ins;
}
}
echo "<pre>";
$s1=Single::getInstance();
$s2=Single::getInstance();
var_dump($s1);
var_dump($s2);
if($s1===$s2){
echo "是一个对象";
}else{
echo "不是一个对象";
}
echo "<hr>";
class Test extends Single{
}
$t1=Test::getInstance();
$t2=Test::getInstance();
var_dump($t1);
var_dump($t2);
echo "<hr>";
$t3=clone $t2;
if($t3===$t2){
echo "是一个对象";
}else{
echo "不是一个对象<br>";
}
var_dump($t3);
/**两个对象什么时间相等
指向一个对象地址的时候,相等
*/
</code></pre>