php教程,四种方案实现单例模式,如何禁止多次实例化?
发布于 作者:苏南大叔 来源:程序如此灵动~单例单例,这个问题是属于老生常谈的问题了。各种编程语言里面针对各种情况,都有各种独特的实现方式。那么,本文中针对的是php
中的类,php
中类如何实现单例模式呢?换句话就是:在同一个php
进程里面,每个类如何实现仅初始化一次。
苏南大叔的“程序如此灵动”技术博客,记录苏南大叔的编程经验总结。本文测试环境:win10
,nginx@1.15.11
,php@8.2.10-nts
。
技术点一:被实例化的方式
因为目标是在php
进程中,禁止类的多次实例化。那么,就需要知道类被实例化的方式。
- 最正统的就是
__construct()
方法,通过new class()
进行初始化。 - 非正统的克隆
__clone()
方法,通过clone $obj
来进行初始化。
所以,为了阻止代码意外的通过传统方式初始化成功。需要改写这两个默认方法属性为private
,并不是说非要置空方法体内容。只是改成private
后,就无法在类外部被意外初始化,会直接报错。例如:
// $aaa = new Sunan();
// Fatal error: Call to private Sunan::__construct() from invalid context
// $bbb = clone Sunan::getInstance();
// Fatal error: Call to private Sunan::__clone() from context
参考文章:
对于类初始化来说,new self()
也是可以初始化的。
技术点二:判断当前类的方法
既然禁用了__construct()
方法,就必须自定义初始化的方法了。这里就可能需要用到__CLASS__
和get_class()
来获得当前类名,以便进行初始化。
这里需要说明的是:__CLASS__
和get_class()
这两种途径,返回的类名是代码在哪个类里面,就返回哪个类的名字,不考虑继承关系的。
参考文章:
技术点三:static静态变量
静态变量实际上是实现单例模式的关键因素之一,本文中的这几个方案里面,静态变量区别就是存在的位置,或者说作用域的区别。它的特点就是一旦被初始化,就跳出初始化的代码逻辑了,进而升级为一个类似全局变量的特殊存在。
如果要对静态变量的用法,有更多的了解,可以参考:
方案一,类的静态属性
class Sunan{
private function __construct(){}
private function __clone(){}
static $instance = null;
public static function getInstance(){
if (self::$instance == null) {
// self::$instance = new Sunan();
$s = __CLASS__;
self::$instance = new $s;
}
return self::$instance;
}
public function sayHi(){
echo "hi,苏南大叔";
}
}
Sunan::getInstance()->sayHi();
方案二,类静态属性+self
class Sunan2{
private function __construct(){}
private function __clone(){}
private static $instance;
public static function getInstance(){
if (!(self::$instance instanceof self)) {
self::$instance = new self();
}
return self::$instance;
}
public function sayHi(){
return "hi,苏南大叔";
}
}
echo Sunan2::getInstance()->sayHi();
方案三,函数里的静态变量
class Sunan3{
private function __construct(){}
private function __clone(){}
public static function getInstance(){
static $instance;
if (!isset($instance)) {
$c = __CLASS__;
$instance = new $c;
}
return $instance;
}
public function sayHi(){
return "hi,苏南大叔";
}
}
echo Sunan3::getInstance()->sayHi();
方案四,总体管控(工厂模式)
class singleton {
public static function getInstance($class){
static $instances = array();
if (!array_key_exists($class, $instances)) {
$instances[$class] = new $class;
}
$target = $instances[$class];
return $target;
}
}
class Sunan9{
public function sayHi() {
echo "hi,苏南大叔";
}
}
singleton::getInstance('Sunan9')->sayHi();
这个方案里面,并没有修改__construct()
和__clone()
为私有,大家想想看,是为啥呢?
相关文章
- https://newsn.net/say/electron-second-instance.html
- https://newsn.net/say/php-static-method.html
- https://newsn.net/say/php-debug-func.html
- https://newsn.net/say/php-reflect-class.html
结束语
单例模式的存在就是为了资源的整合,比如入数据库查询的时候,如果不使用单例模式的话,每次页面刷新都可能会带来大量的数据库接入操作,进而引发“too many connections”的类似问题。
苏南大叔总结php
代码文章,可以参考:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。