概念
单例模式 (Singleton Pattern),是一种常用的软件设计模式。通过单例模式可以保证系统中一个类仅有一个对象实例。
- 构造函数是私有的:仅供内部初始化时创建
- 定义该类的静态私有对象:instance变量
- 定义一个静态的公有的函数:用于初始化或获取它本身的静态私有对象
- 禁止拷贝对象:重写__clone(),里面空实现
应用场景
资源共享的情况下,会使用单例模式,避免由于资源操作时导致的性能或损耗等。通常
服务
类型的可以设置成单例,如mysql,redis,kafka,rabbitmq等。
先上代码,是一个redis实例化的例子
<?php
namespace App\learn;
use Predis\Client;
class Redis
{
private static $instance;
private static $host;
private static $port;
private function __construct($host, $port)
{
self::$host = $host;
self::$port = $port;
return new Client($host, $port);
}
public static function getInstance($host, $port)
{
if (!self::$instance instanceof self) {
self::$instance = new self($host, $port);
}
return self::$instance;
}
/**
* 禁止克隆
*/
private function __clone()
{
}
}
$redis = Redis::getInstance('192.168.43.243', 6379);
需要明白几个知识点
- instance变量为什么是private和static?
instance变量是用于getInstance方法返回redis实例的,所以该变量不需要外部访问,定义成private即可。
静态成员是类属性。传统php-fpm模式下,在一次请求中,无论类实例化多少次,类中的静态成员是不会重置的,是驻内存的,在请求结束后,内存释放,变量也就释放。如果在swoole,java等编译型语言中,静态成员是在第一次调用后就会常驻内存的,也就是该静态成员是不会随着每次请求而释放的,所以单例在常驻内存的语言中是很有优势的。那么在传统php中是不是就没什么意义了呢?在多次请求的角度肯定没意义的,我们站在单次请求的角度出发,如果一次请求中有多次类实例化,此时如果使用单例模式的话可以避免多次实例造成资源浪费,毕竟单例模式就是保证系统中类只有一个实例化对象,避免造成资源浪费。 - 构造函数为什么是private?
因为实例化redis,我们只希望在getInstance中实例化,如果用户想获得redis实例调用getInstance方法即可,我们并不希望用户在外部可以直接new redis()。只要把构造函数设置成private即可实现上述。 - getInstance方法为什么是public和static?
首先getInstance方法是外部用户调用redis实例的方法,既然外部可以调用肯定是public修饰符。
由于获取redis实例是通过外部调用getInstance方法来实现的,而此时我们构造方法又是private修饰符,所以如果想实现外部可以调用getInstance方法,我们只能将该getInstance方法设置成静态的,这样用户直接使用类::getInstance()的方式来获取类的实例了。 - __clone()为什么设置成private
首先__clone()是一个魔术方法,_clone()魔术方法只是在对象被克隆时会触发的方法。任何对象都是可以使用关键字clone来克隆的。
$home = new Home();
$cloneHome = clone $home;
如果将__clone魔术方法设置成private,则代码禁止克隆,上述代码在使用关键字clone时就会提示错误。
网友评论