设计模式专题(十七) ——单例模式

设计模式专题(十七)——单例模式

(原创内容,转载请注明来源,谢谢)

一、概述

单例模式(Singleton)保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常会在类内部提供一个变量存储自身的实例,保证没有其他实例被创建,保证该实例是类的唯一实例。

单例模式可以严格控制客户的访问方式,保证唯一的实例。

二、多线程情况下的单例

当多线程中,多个线程同时访问类,还是有可能会创建出多个实例,则需要加锁。锁是为了保证代码处于临界区时,另一个线程不进入临界区。

当程序被上锁,其他访问的程序会阻塞,直等到锁被释放才可以访问。另外,需要在上锁之前加一层判断,如果类已经实例化,则直接返回类的实例,而不需要去加锁后再判断。

三、PHP中的单例模式

PHP由于很少涉及到多线程,因此通常不需要进行加锁。另外,由于PHP的页面被执行后,所有的变量都会被回收,这也使得PHP语言级别上无法实现变量的常驻(除非通过将实例化的遍历序列化后存在redis或memcache等缓存中实现)。

因此,对于php而言,单例模式通常是为了防止单个页面高并发的情况下,实例化太多类出现的问题。

最常见的就是对数据库的连接采用单例模式,因为mysql数据库有最大连接数限制,当大量的连接发生,会导致无法连接数据库,则可以实现单例模式。

四、单例模式要点

1、私有化构造函数和克隆函数

php的魔术方法构造函数和克隆函数,需要设置成private,这样用户就无法通过new的方式获取类的实例化。

2、定义一个私有化静态变量,用于存储类的实例化。

3、定义一个public的静态方法,去判断上述变量是否有内容,有则返回,没有则进行实例化。

五、单例模式实现数据库连接

<?php
//单例模式实现数据库连接
class Db{
         private static $ins;
         private static $conn;
         private function__construct(){}
         private function__clone(){}
         public static functiongetInstance(){
                   if(null ==self::$ins || !(self::$ins instanceof self)){
                            self::$ins= new self();
                            self::$conn= new PDO('mysql:host=127.0.0.1;dbname=testdb,root,root');
                   }
                   returnself::$ins;     
         }
         public functiongetConn(){
                   return$this->conn;
         }
}

——written by linhxx 2017.08.15

相关阅读:

设计模式专题(十六)——迭代器模式

设计模式专题(十五) ——组合模式

设计模式专题(十四)——适配器模式

设计模式专题(十三) ——备忘录模式

设计模式专题(十二)——状态模式

设计模式专题(十一)——抽象工厂模式

设计模式专题(十)——观察者模式

设计模式专题(九) ——外观模式

设计模式专题(八) ——模板方法模式

设计模式专题(七)——建造者模式

设计模式专题(六)——原型模式

设计模式专题(五)——工厂方法模式

设计模式专题(四)——代理模式

设计模式专题(三)——装饰模式

设计模式专题(二)——策略模式

设计模式专题(一)——面向对象的设计原则

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-08-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏青玉伏案

算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)

数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用。因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队...

16910
来自专栏程序员互动联盟

【编程基础】聊聊C语言-我的地盘我做主

上一篇我们讲了变量的寿命,知道了C语言的变量是有生命周期的。到了一定的时机它们所占用的内存就会被释放。接下来我们讲讲这些变量都存储在哪些地盘上以及它们各自的势力...

3095
来自专栏Crossin的编程教室

Python 中的 time 模块

写代码时,常常会遇到处理时间和日期的问题。在 Python 中,与时间处理最相关的模块是 time 和 datetime。今天我们介绍下 time 模块的常用功...

2608
来自专栏MyBlog

Effective Java 读书笔记(7)避免finalizer

对于Finalizers他们的使用可能会造成错误的产生,糟糕的性能以及移植性的问题,当然Finalizers有着一些有用的优点,我们会在后续介绍这些,但是作为首...

732
来自专栏程序小工

【实战】Tp5+小程序(一)--数据库访问与ORM

ThinkPHP5 从入门到深入学习,结合实战项目深入理解 ThinkPHP5 的特性和使用方法,了解 ThinkPHP5 的数据库访问和 ORM 思想,学习使...

792
来自专栏架构说

缓存策略之LRU实现及分析

LRU定义 Cache的容量有限,因此当Cache的容量用完后,而又有新的内容需要添加进来时, 就需要挑选并舍弃原有的部分内容,从而腾出空间...

29910
来自专栏Golang语言社区

【Go 语言社区】Go语言转换所有字符串为大写或者小写的方法

本文实例讲述了Go语言转换所有字符串为大写或者小写的方法。分享给大家供大家参考。具体如下: Go语言的string模块包含了ToLower和ToUpper函数,...

33410
来自专栏MoeLove

理解Redis的RESP协议

Redis 的客户端和服务端之间采取了一种独立的名为 RESP(REdis Serialization Protocol) 的协议,作者主要考虑了以下几个点:

441
来自专栏对角另一面

lodash源码分析之缓存方式的选择

本文为读 lodash 源码的第八篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash

1889
来自专栏欧阳大哥的轮子

深入解构objc_msgSend函数的实现

熟悉OC语言的Runtime(运行时)机制以及对象方法调用机制的开发者都知道,所有OC方法调用在编译时都会转化为对C函数objc_msgSend的调用。

542

扫描关注云+社区