前提
提到单例模式,那就不得不说设计模式。
单例模式是最简单的一种设计模式,提供了一种唯一访问其对象的方式,可以直接访问。
属于创建型模式
实现之前,我们先要明白两个关键字的原理
static
- 声明类属性或方法为静态,就可以不实例化类而直接访问。静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
- 函数体中的静态变量与全局中的静态变量不冲突,只有在关键字global作用下才会使局部与全局统一
- 函数体中的静态变量在函数调用的时候只会被初始化一次
- 静态方法可以调用静态属性,禁止调用非静态属性
- class::method()调用本方法所在类,static::method()调用最后定义的方法
静态变量和全局变量均存放于全局区,程序结束后仍存于内存
也就是说,当我们定义了一个静态变量,就可以在全局访问它的属性
clone
创建一个对象的副本。
只有在使用clone关键字时,__clone方法才会被调用
<?php
class A {
public function __clone() {
echo "clone function is being used" . "\n";
}
public $a;
}
$classA = new A();
$classB = $classA;
$classC = clone $classA;
echo "A === B ? :" . ($classA === $classB ? 'true' : 'false') . "\n";
echo "A === C ? :" . ($classA === $classC ? 'true' : 'false') . "\n";
?>
php的clone()方法对一个对象实例进行的浅复制,对象内的基本数值类型进行的是传值复制,而对象内的对象型成员变量,如果不重写clone方法,显式的clone这个对象成员变量的话,这个成员变量就是传引用复制,而不是生成一个新的对象.
浅复制时,属性为对象的,属性值仍然指向同一个变量地址
深复制则两者完全无关,通过 __clone 方法将对象属性加上重赋值
或者 在复制时使用unserialize(serialize($obj));
因此在复制的过程中我们需要注意,它究竟是浅复制还是深复制
单例模式实现
OK,利用以上的关键字,我们就可以设计出一个比较合理的单例模式,将构造函数和__clone函数设为私有防止外界实例化或者克隆对象。
class InstanceClass
{
private static $instances;
private function __construct()
{
}
private function __clone()
{
}
/**
* @return static
*/
public static function getInstance()
{
if (!isset(self::$instances)) {
self::$instances = new $InstanceClass;
}
return self::$instances;
}
}
只能通过getInstance方法来调用对象
但其实这样还是不完善,如何解决多线程单例模式,以及在多继承中使用单例等等
这里就不多说啦~~~~~
哈哈