在PHP的面向对象开发中,单例模式很常见。它主要用于,保证在一个进程中某对象的唯一性,并防止重复创建。举个例子,地球只有一个,那么我们在创建地球实例的时候,就不能重复创建。那么如何办到呢?这就要用到单例模式。
如何使用单例模式呢?既然,一个实例只能被创建一次,那么,我们必须保证每次拿到的实例都是同一个实例。那在类中,我们该如何保证呢?首先,我们都知道类中有一个静态对象,各实例都是共享这个对象的,那么我们就可以完全利用这个特性。把让静态对象指向这个创建好的实例。当再次需要此实例时,直接返回不再重复创建。如下例:
class Earth {
//用来指向已创建好的实例
public static $instance;
//获取已创建好的实例,当实例不存在就创建,存在就直接返回
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
这样,一个半成品的单例模式类就创建好了。是不是很简单呢?此时,我们可以通过调用Earth::getInstance();方法来获取这个对象实例了。那么有人要说了,如果我不用getInstance(), 就想相接new Earth()。也可以创建对象实例。而且可以多次创建不同的实例。那怎么办?那就把它封死。让__construct方法不可被外部调用。如下:
class Earth {
//用来指向已创建好的实例
public static $instance;
//把对外的初始化封死
private function __construct()
{
}
//获取已创建好的实例,当实例不存在就创建,存在就直接返回
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
这时候,想要创建实例,就必须通过调用getInstance()方法进行获取了。聪明的PHP程序员,总是不会被各种困难吓倒的。他们找到了新的方法来创建多个实例对象。看下面的例子:
$earth = Earth::getInstance();
$newEarth = clone $earth;
$newNewEarth = clone $earth;
那么,我们就把clone这个道儿也给它封了。我们知道,在对象调用clone方法时,内核会自动调用类对象的__clone()方法
。于是我们稍加修改如下:
class Earth
{
//用来指向已创建好的实例
public static $instance;
//把对外的初始化封死
private function __construct()
{
}
//调用clone时什么都不返回,达到不允许复制对象的目的
public function __clone()
{
}
//获取已创建好的实例,当实例不存在就创建,存在就直接返回
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
于是一个实现单例模式的类就完成了,是不是很简单呢?从我们一步步的完成单例的过程中,我们看到,基本上是在对创建对象实例进行限制,所以单例模式其实就是一种限制型的设计模式。对创建的限制来满足业务的需求。