php 单例模式

本文深入探讨单例模式的实现原理及应用场景,强调其在资源管理、数据库连接池、线程池设计等方面的重要作用,以及如何避免多实例带来的性能损耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在面向对象中,一个对象只负责一个特定的任务通常是一种很好的选择。例如:你只想让一个对象去访问数据库。单例模式是一种职责模式,他将创建的对象委托到一个单一的访问点上。在任何时候,应用程序中都只有这个类仅有的一个实例存在。这可以防止我们去打开数据库的多个连接或者不必要使用多余的系统资源。在更加复杂的系统中,使用单例模式在维持应用程序状态同步方面也尤为重要。

PS:同步一般是对于语言多线程方面的应用,PHP 本身不支持多线程

在这里插入图片描述

业务逻辑异常,和同步的问题都是没有使用单利模式的,多个数据库连接的对象产生的问题 ,所以要使用单利模式

a.php

<?php
require 'DB.class.php';

$_a = new DB();
var_dump($_a->query("SELECT * FROM cms_user"));

echo '<br />';
#怎么才能创建第二次数据库连接对象呢 需要在new下  没有严格控制只能生成一个 
$_a = new DB();
var_dump($_a->query("SELECT * FROM cms_user"));

echo '<br />';
var_dump($_a->query("SELECT * FROM cms_user"));
?>

DB.class.php

<?php
class DB {
	private $_db;
	public function __construct() {
		try {
			$this->_db = new PDO('mysql:host=localhost;dbname=test','root','');
			echo '创建了一次数据库链接对象';
		} catch (PDOException  $e) {
			exit($e->getMessage());
		}
	}
	public function query($_sql) {
		return $this->_db->query($_sql);
	}
}
?>

在这里插入图片描述

<?php
require 'DB.class.php';
require 'Action.class.php';
require 'Article.class.php';
require 'Photo.class.php';
require 'User.class.php';


$_article = new Article();
var_dump($_article->query("SELECT * FROM cms_adver"));

echo '<br />';

$_photo = new Photo();
var_dump($_photo->query("SELECT * FROM cms_link"));


echo '<br />';

$_user = new User();
var_dump($_user->query("SELECT * FROM cms_user"));

<?php
abstract class Action {
	protected $_db;
	public function __construct() {
		#这几个代码被继承一次,就执行一次,继承一次,就执行一次 
		$this->_db = new DB();
	}
	abstract public function query($_sql);
}
?>
<?php
class Article extends Action {
	public function query($_sql) {
		return $this->_db->query($_sql);
	}
}
?>
<?php
class DB {
	private $_db;
	public function __construct() {
		try {
			$this->_db = new PDO('mysql:host=localhost;dbname=cms','root','yangfan');
			echo '创建了一次数据库链接对象';
		} catch (PDOException  $e) {
			exit($e->getMessage());
		}
	}
	public function query($_sql) {
		return $this->_db->query($_sql);
	}
}
?>
<?php
class Photo extends Action {
	public function query($_sql) {
		return $this->_db->query($_sql);
	}
}
?>

根本不能实现只实例化一次对象

单例类所需的三个公共元素:

  1. 必须拥有一个构造方法,并且必须被标记为 private;
  2. 拥有一个保存类的实例的静态成员属性(字段);
  3. 拥有一个访问这个实例的公共的静态方法

静态的直接访问
在这里插入图片描述
#a.php

<?php
require 'DB.class.php';
require 'Action.class.php';
require 'Article.class.php';
require 'Photo.class.php';
require 'User.class.php';


$_article = new Article();
var_dump($_article->query("SELECT * FROM cms_adver"));

echo '<br />';

$_photo = new Photo();
var_dump($_photo->query("SELECT * FROM cms_link"));

echo '<br />';

$_user = new User();
var_dump($_user->query("SELECT * FROM cms_user"));
?>

#Action.class.php

<?php
abstract class Action {
	protected $_db;
	public function __construct() {
		$this->_db = DB::getInstance();
	}
	abstract public function query($_sql);
}
?>

#Article.class.php

<?php
class Article extends Action {
	public function query($_sql) {
		return $this->_db->query($_sql);
	}
}
?>

#DB.class.php
#单一职责问题,一个对象实现一个任务

<?php
class DB {
	private $_db;
	//静态是通过类::字段直接访问的,private表示外部不能访问
	static private $_instance;
	//访问这个实例的公共静态方法
	#如果是静态的就用self表示DB本身
	static public function getInstance() {
		//如果对象没有创建,就创建它,如果创建了,就直接返回
		if (!(self::$_instance instanceof self)) {
			self::$_instance = new self();
		}
		#new DB 类的里面可以new DB()
		#return new DB();
		return self::$_instance;
	}
	//单一职责问题,私有化克隆
	private function __clone() {}
	//私有化构造方法,
	private function __construct() {
		try {
			$this->_db = new PDO('mysql:host=localhost;dbname=cms','root','yangfan');
			echo '创建了一次数据库链接对象';
		} catch (PDOException  $e) {
			exit($e->getMessage());
		}
	}
	public function query($_sql) {
		return $this->_db->query($_sql);
	}
}
?>

Photo.class.php

<?php
class Photo extends Action {
	public function query($_sql) {
		return $this->_db->query($_sql);
	}
}
?>

#User.class.php

<?php
class User extends Action {
	public function query($_sql) {
		return $this->_db->query($_sql);
	}
}
?>

单例模式可以很好的替代全局变量。虽然单例模式也存在和全局变量一样的缺点 ,比如依赖性,因此我们应当小心谨慎的使用单例模式

将数据库的对象,创建的永远保持一个,节约空间,保持正常和同步

单例模式(Singleton)也叫单态模式,是设计模式中最为简单的一种模式,甚至有些模式大师都不称其为模式,称其为一种实现技巧,因为设计模式讲究对象之间的关系的抽象,而单例模式只有自己一个对象,也因此有些设计大师并把把其称为设计模式之一。

这里又不具体讲如何实现单例模式和介绍其原理(因为这方便的已经有太多的好文章介绍了)

好多没怎么使用过的人可能会想,单例模式感觉不怎么用到,实际的应用场景有哪些呢?以下,我将列出一些就在咱们周边和很有意义的单例应用场景。

  1. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~
  2. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。
  3. 网站的计数器,一般也是采用单例模式实现,否则难以同步。
  4. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
  5. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。
  6. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。
  7. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。
  8. 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。
  9. HttpApplication 也是单位例的典型应用。熟悉http://ASP.Net(IIS)的整个请求生命周期的人应该知道HttpApplication也是单例模式,所有的HttpModule都共享一个HttpApplication实例.

总结以上,不难看出:

单例模式应用的场景一般发现在以下条件下:

  1. 资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
  2. 控制资源的情况下,方便资源之间的互相通信。如线程池等。

单例模式之继承碰见的问题

《编译原理》是计算机科学中一门极为重要的课程,主要探讨如何将高级程序设计语言转换成机器可执行的指令。清华大学的张素琴教授在这一领域有着深厚的学术造诣,其编译原理课后习题答案对于学习者而言是非常珍贵的资源。这份压缩文件详细解析了课程中所涉及的概念、理论和方法的实践应用,目的是帮助学生更好地理解编译器设计的核心内容。 编译原理的核心知识点主要包括以下几点: 词法分析:作为编译过程的首要环节,词法分析器会扫描源代码,识别出一个个称为“标记”(Token)的最小语法单位。通常借助正则表达式来定义各种标记的模式。 语法分析:基于词法分析产生的标记流,语法分析器依据文法规则构建语法树。上下文无关文法(CFG)是编译器设计中常用的一种形式化工具。 语义分析:这一步骤用于理解程序的意义,确保程序符合语言的语义规则。语义分析可分为静态语义分析和动态语义分析,前者主要检查类型匹配、变量声明等内容,后者则关注运行时的行为。 中间代码生成:编译器通常会生成一种高级的中间表示,如三地址码或抽象语法树,以便于后续的优化和目标代码生成。 代码优化:通过消除冗余计算、改进数据布局等方式提升程序的执行效率,同时不改变程序的语义。 目标代码生成:根据中间代码生成特定机器架构的目标代码,这一阶段需要考虑指令集体系结构、寄存器分配、跳转优化等问题。 链接:将编译后的模块进行合并,解决外部引用,最终形成一个可执行文件。 错误处理:在词法分析、语法分析和语义分析过程中,编译器需要能够检测并报告错误,例如语法错误、类型错误等。 张素琴教授的课后习题答案覆盖了上述所有核心知识点,并可能包含实际编程练习,比如实现简单的编译器或解释器,以及针对特定问题的解题策略。通过解答这些习题,学生可以加深对编译原理的理解,提升解决问题的能力,为今后参与编译器开发或软件工程实践奠定坚实的基础。这份资源不仅是学习编译原理的有力辅助材料,也是
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟伟哦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值