热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PHP中的单例模式与静态变量的区别及使用方法

本文介绍了PHP中的单例模式与静态变量的区别及使用方法。在PHP中,静态变量的存活周期仅仅是每次PHP的会话周期,与Java、C++不同。静态变量在PHP中的作用域仅限于当前文件内,在函数或类中可以传递变量。本文还通过示例代码解释了静态变量在函数和类中的使用方法,并说明了静态变量的生命周期与结构体的生命周期相关联。同时,本文还介绍了静态变量在类中的使用方法,并通过示例代码展示了如何在类中使用静态变量。

在PHP中,没有普遍意义上的静态变量。与Java、C++不同,PHP中的静态变量的存活周期仅仅是每次PHP的会话周期,所以注定了不会有Java或者C++那种静态变量。

静态变量在PHP中

在PHP中,静态变量的存在意义仅仅是在某个结构体中(方法或者类)中传递一个变量,其作用域在此文件内。

function test(){
    static $var = 1; 
    echo $var++.'';
}
test();
test();
test();
//OutPut
//1
//2
//3

在函数test的三次调用中,变量$var在三次调用中都是存在的,并且每次会递增1,而并没有清空或者重置
所以可以得出一个结论,静态变量在当前结构体所在的生命周期中一直存在。当前的例子中,test函数的生命周期就是当前PHP脚本,只要程序没释放都是有效的。

静态变量在类中

而在类中,代码大概是这样子的

class A
{
    private static $a = 1; 
    private $b = 2;
    public function add()
    {
        echo self::$a++.'';
        echo $this->b++.'';
    }
}
$class1 = new A();
$class1->add();
$class1->add();
$class2 = new A();
$class2->add();
$class2->add();
//Output
//1
//2
//2
//3
//3
//2
//4
//3

从上面的类的运行结果来看,也得到了在函数中相同的结果

那么大概总结一下就是

PHP的静态变量在所在对应的结构体的生命周期中永久存在,并且值保持一致,不论这个结构体被调用或者实例化了多少次。

其实这就是动态变量和静态变量的区别,具体看此篇文章。动态变量只在类中有效,而静态变量在当前php脚本。

静态变量在单例模式中

再反过来看单例模式

class A
{
    private static $instance = null;
    private $b = 1;
    public static function get_instance()
    {
        if(self::$instance == null){
            $classname = __CLASS__;
            self::$instance = new $classname(); 
        }
        return self::$instance;
    }
    public function add()
    {
        $this->b++;
    }
    public function show()
    {
        echo $this->b;
    }
}
$a = A::get_instance();
$b = A::get_instance();
//此处$a和$b变量完全相同!
$a->add();
$a->show();
echo '';
$b->show();
//output
//2
//2

此时,由于单例模式存在,使得$a和$b完全是同一个对象,所以之间如果需要共享数据,完全不需要静态变量(废话,就是自己。因为在任何时候,应用程序中都只会有这个类仅有的一个实例存在!无论你调用多少次单例,里面的数据是不会被重新实例化的。)

所以,在单例模式中,静态变量根本就没有存在的意义。当然,如果你没事干,非要使用new方法来初始化对象的话,也行,此时单例模式被打破,回归到无单例模式的状态。

如果为了防止使用new来实例化对象,那么可以考虑对类的__construct函数设置为private属性

class A
{
    private static $instance = null;
    private $b = 1;
    private function __construct()
    {
    //Code in this function
    //could not be get out of the class
    }
    public static function get_instance()
    {
        if(self::$instance == null){
            $classname = __CLASS__;
            self::$instance = new $classname();
        }
        return self::$instance;
    }
    public function add()
    {
        $this->b++;
    }
    public function show()
    {
        echo $this->b;
    }
}
$a = A::get_instance();
$b = A::get_instance();
//此处$a和$b 变量完全相同!
$a->add();
$a->show();
echo '
';
$b->show();
//output
//2
//2
  
//如果尝试用new来实例化的话
$c = new A();
//output
//Fatal error: Call to private A::__construct() from invalid context in
//如果需要A类的实例化对象,只能通过开放的get_instance静态方法进行初始化

优点:单例模式可以避免大量的new操作,因为每一次new操作都会消耗内存资源和系统资源

缺点:在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的

相关教程推荐:《PHP教程》


推荐阅读
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • ECMA262规定typeof操作符的返回值和instanceof的使用方法
    本文介绍了ECMA262规定的typeof操作符对不同类型的变量的返回值,以及instanceof操作符的使用方法。同时还提到了在不同浏览器中对正则表达式应用typeof操作符的返回值的差异。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • 本文介绍了Java中Currency类的getInstance()方法,该方法用于检索给定货币代码的该货币的实例。文章详细解释了方法的语法、参数、返回值和异常,并提供了一个示例程序来说明该方法的工作原理。 ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
author-avatar
曼珠沙華的朦朧_759
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有