关键词:
使用单例模式的出发点:
1、php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源。
2、如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。
3、在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。
创造单例注意:
1、一个雷只能有一个类对象(只能实例化一个对象)
2、它必须自己创建这个实例
3、它必须自行向整个系统提供这个实例
4、构造函数和克隆函数必须声明为私有的,这是为了防止外部程序 new 类从而失去单例模式的意义
5、 getInstance()方法必须声明为公有的,必须调用此方法以返回唯一实例的一个引用
6、拥有一个保存类的实例的静态成员变量
7、PHP的单例模式是相对而言的,因为PHP的解释运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收
8、拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)
另外,需要创建__clone()方法防止对象被复制(克隆)
代码如下:
1 <?php 2 class Danli 3 { 4 5 //保存类实例的静态成员变量 6 private static $_instance; 7 8 //private标记的构造方法 9 private function __construct() 10 { 11 echo ‘This is a Constructed method;‘; 12 } 13 14 //创建__clone方法防止对象被复制克隆 15 public function __clone() 16 { 17 trigger_error(‘Clone is not allow!‘, E_USER_ERROR); 18 } 19 20 //单例方法,用于访问实例的公共的静态方法 21 public static function getInstance() 22 { 23 if (!(self::$_instance instanceof self)) { 24 self::$_instance = new self; 25 } 26 return self::$_instance; 27 } 28 29 public function test() 30 { 31 echo ‘调用方法成功‘; 32 } 33 34 } 35 36 /*用new实例化private标记构造函数的类会报错 37 $danli = new Danli(); 38 39 复制(克隆)对象将导致一个E_USER_ERROR 40 $danli_clone = clone $danli; 41 */ 42 43 44 //正确方法,用双冒号::操作符访问静态方法获取实例 45 $danli = Danli::getInstance(); 46 $danli->test(); 47 ?>
运用单例模式实现一个数据库类:
1 <?php 2 class DBHelper 3 { 4 private $link; 5 static private $_instance; 6 7 // 连接数据库 8 private function __construct($host, $username, $password) 9 { 10 $this->link = mysql_connect($host, $username, $password); 11 $this->query("SET NAMES ‘utf8‘", $this->link); 12 //echo mysql_errno($this->link) . ": " . mysql_error($link). "n"; 13 //var_dump($this->link); 14 return $this->link; 15 } 16 private function __clone() 17 { 18 } 19 public static function get_class_nmdb($host, $username, $password) 20 { 21 //$connector = new nmdb($host, $username, $password); 22 //return $connector; 23 24 if (FALSE == (self::$_instance instanceof self)) { 25 self::$_instance = new self($host, $username, $password); 26 } 27 return self::$_instance; 28 } 29 // 连接数据表 30 public function select_db($database) 31 { 32 $this->result = mysql_select_db($database); 33 return $this->result; 34 } 35 // 执行SQL语句 36 public function query($query) 37 { 38 return $this->result = mysql_query($query, $this->link); 39 } 40 // 将结果集保存为数组 41 public function fetch_array($fetch_array) 42 { 43 return $this->result = mysql_fetch_array($fetch_array, MYSQL_ASSOC); 44 } 45 // 获得记录数目 46 public function num_rows($query) 47 { 48 return $this->result = mysql_num_rows($query); 49 } 50 // 关闭数据库连接 51 public function close() 52 { 53 return $this->result = mysql_close($this->link); 54 } 55 } 56 $connector = DBHelper::get_class_nmdb($host, $username, $password); 57 $connector -> select_db($database); 58 ?>
也可以参考这个类实现:
1 <?php 2 /* 3 * mysql 单例 4 */ 5 class mysql{ 6 private $host =‘localhost‘; //数据库主机 7 private $user = ‘root‘; //数据库用户名 8 private $pwd = ‘‘; //数据库用户名密码 9 private $database = ‘imoro_imoro‘; //数据库名 10 private $charset = ‘utf8‘; //数据库编码,GBK,UTF8,gb2312 11 private $link; //数据库连接标识; 12 private $rows; //查询获取的多行数组 13 static $_instance; //存储对象 14 /** 15 * 构造函数 16 * 私有 17 */ 18 private function __construct($pconnect = false) { 19 if (!$pconnect) { 20 $this->link = @ mysql_connect($this->host, $this->user, $this->pwd) or $this->err(); 21 } else { 22 $this->link = @ mysql_pconnect($this->host, $this->user, $this->pwd) or $this->err(); 23 } 24 mysql_select_db($this->database) or $this->err(); 25 $this->query("SET NAMES ‘{$this->charset}‘", $this->link); 26 return $this->link; 27 } 28 /** 29 * 防止被克隆 30 * 31 */ 32 private function __clone(){} 33 public static function getInstance($pconnect = false){ 34 if(FALSE == (self::$_instance instanceof self)){ 35 self::$_instance = new self($pconnect); 36 } 37 return self::$_instance; 38 } 39 /** 40 * 查询 41 */ 42 public function query($sql, $link = ‘‘) { 43 $this->result = mysql_query($sql, $this->link) or $this->err($sql); 44 return $this->result; 45 } 46 /** 47 * 单行记录 48 */ 49 public function getRow($sql, $type = MYSQL_ASSOC) { 50 $result = $this->query($sql); 51 return @ mysql_fetch_array($result, $type); 52 } 53 /** 54 * 多行记录 55 */ 56 public function getRows($sql, $type = MYSQL_ASSOC) { 57 $result = $this->query($sql); 58 while ($row = @ mysql_fetch_array($result, $type)) { 59 $this->rows[] = $row; 60 } 61 return $this->rows; 62 } 63 /** 64 * 错误信息输出 65 */ 66 protected function err($sql = null) { 67 //这里输出错误信息 68 echo ‘error‘; 69 exit(); 70 } 71 } 72 //用例 73 $db = mysql::getInstance(); 74 $db2 = mysql::getInstance(); 75 $data = $db->getRows(‘select * from blog‘); 76 //print_r($data); 77 //判断两个对象是否相等 78 if($db === $db2){ 79 echo ‘true‘; 80 } 81 ?>
PHP单例模式的缺点
众所周知,PHP语言是一种解释型的脚本语言,这种运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收。也就是说,PHP在语言级别上没有办法让某个对象常驻内存,这和asp.net、Java等编译型是不同的,比如在Java中单例会一直存在于整个应用程序的生命周期里,变量是跨页面级
的,真正可以做到这个实例在应用程序生命周期中的唯一性。然而在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面
级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的。
用单例模式实现主jframe不变,只有jpanel面板切换
1、首先介绍一下什么是单例模式: java单例模式是一种常见的设计模式,那么我们先看看懒汉模式:publicclassSingleton_{//设为私有方法,防止被外部类引用或实例privateSingleton_(){System.out.println("懒汉单例模式");}privatestaticSingleton_... 查看详情
java单例模式
...类保证只有一个实例,并提供统一的访问入口。为什么要用单例模式节省内存节省计算如对象实例中的一样的,那就不用每次都创建一个对象方便管理因为单例提供一个统一的访问入口,不需要创建N多个对象,很多工具类都用... 查看详情
单例模式(代码片段)
...要求生产唯一序列号。WEB中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。创建的一个对象需要消耗的资源过多,比如I/O与数据库的连接等。注意事项:getInstance()方法中需要使用同步锁synchronized(Singleton.class)... 查看详情
简单的单例模式(代码片段)
...这个类只有一个实例假如在下面这种情况下,我们有一个数据库连接类,在平常的时候,我们实例化这个类然后写入连接,第一次我链接了SQLServer数据库,第二次我链接了MySql数据库,但是我同时想用这两个数据库,发现不太合... 查看详情
23种设计模式一:单例模式
...要求生产唯一序列号。WEB中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。创建的一个对象需要消耗的资源过多,比如I/O与数据库的连接等。2、实现我们将创建一个SingletonDemo类,它有私有的构造函数和本身... 查看详情
单例模式俗称单例3步曲+1曲
...模式。为什么要用单例模式? 1。php常常和数据库打交道,如果在应用中频繁建立连接对象,进行new操作的话,会消耗大量的系统 查看详情
面向对象之单例模式(代码片段)
目录1.单例模式1.1什么是单例模式1.2为什么用单例模式1.3单例模式三种方式1.3.1使用类内部绑定方法特性,定义静态方法1.3.2利用装饰器实现单例模式1.3.3利用元类实现单例模式1.单例模式1.1什么是单例模式单例模式就是基于某种... 查看详情
php-单例模式(代码片段)
...pClassDatabase$db=newDatabase;这是最常规的实例化操作方法,像数据库操作的方法类,如果多次进行new操作,将消耗更多的系统资源,那么有什么好的方法了?什么是单例模式?1)一个类只能有一个实例2)由类自行创建实例3)类自行... 查看详情
厉害了,美女同事用单例模式实现了雪花算法!(代码片段)
...雪花算法雪花算法适用于生成全局唯一的编号,比如数据库主键id,订单编号等至于为什么叫雪花算法,是因为科学家通过研究认为自然界中不存在两片完全相同的雪花,所以这种算法用雪花来命名也是强调它生... 查看详情
设计模式--单例模式(代码片段)
...模式。我们这节就全面的来讲解一下单例模式。为什么要用单例模式单例模式理解起来非常简单。在一个系统中,一个类只允许创建一个对象,那这个类就是单例类,这种设计模式就叫做单例设计模式。为什么需要单例模式呢?... 查看详情
单例模式
运行期间有且仅有一个实例。(比较耗系统性能的时候用单例模式)关键点:1,一个类只有一个实例,只提供私有的构造器2,它必须自行创建这个实例,定义了静态的该类的私有对象3,它必须自行向整个系统提供这个实例,提... 查看详情
设计模式之php项目应用——单例模式设计memcache和redis操作类
...目应用4.1需求说明 CleverCode在实际的PHP项目中,应用单例模式最多的就是涉及到网络连接的。比如Memcache和Redis连接,一般的需求通常Redis都只有一台服务器,所以用单例模式将连接封装到getInstance(),这样做的好... 查看详情
单例模式
...例php中使用单例模式的原因我用php大部分操作都是和各种数据库打交道,包括mysql,redis,memcache等各种关系型和非关 查看详情
laravel框架中运用单例模式(代码片段)
阅读目录解决问题场景单例模式控制器模型打印finalModel父类模型Model子类控制器打印解决问题场景发现在代码中不断的在newmodel()调用模型方法,这样子会不断的对模型进行实例化,并不断的销毁对象。比如:<?phpnamespaceApp\\Http\\... 查看详情
设计模式之单例模式
...序列号。 2、WEB中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。 3、创建的一个对象需要消耗的资源过多,比如I/O与数据库的连接等。定义: 确保一个类只有一个实例,并为整个系统提... 查看详情
单例模式(代码片段)
...景要求生产唯一序列号WEB中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来创建的一个对象需要消耗的资源过多,比如I/O与数据库的连接等。注意get 查看详情
单例模式(singleton-pattern)百媚生
...唯一序列号。 2、WEB中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。 3、创建的一个 查看详情
javascript设计模式与开发实践阅读笔记——单例模式
...论我点击多少次这个浮窗都只会被创建一次,这里就可以用单例模式。1.实现单例模式思路:用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象 查看详情