**在有些系统中,为了节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。** ## 单例模式的定义与特点 单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。 在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。 单例模式在现实生活中的应用也非常广泛,例如公司 CEO、部门经理等都属于单例模型。J2EE 标准中的[Servlet](http://c.biancheng.net/servlet/)Context 和 ServletContextConfig、[Spring](http://c.biancheng.net/spring/)框架应用中的 ApplicationContext、数据库中的连接池等也都是单例模式。 单例模式有 3 个特点: 1. 单例类只有一个实例对象; 2. 该单例对象必须由单例类自行创建; 3. 单例类对外提供一个访问该单例的全局访问点。 ## 单例模式的优点和缺点 单例模式的优点: * 单例模式可以保证内存里只有一个实例,减少了内存的开销。 * 可以避免对资源的多重占用。 * 单例模式设置全局访问点,可以优化和共享资源的访问。 单例模式的缺点: * 单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。 * 在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。 * 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。 * 单列模式在业务代码中加入和业务无关的代码 > 单例模式看起来非常简单,实现起来也非常简单。单例模式在面试中是一个高频面试题。希望大家能够认真学习,掌握单例模式,提升核心竞争力,给面试加分,顺利拿到 Offer。 单例模式应用的场景一般发现在以下条件下:   (1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。   (2)控制资源的情况下,方便资源之间的互相通信。如线程池等。 ## 单例模式的结构与实现 单例模式是[设计模式](http://c.biancheng.net/design_pattern/)中最简单的模式之一。通常,普通类的构造函数是公有的,外部类可以通过“new 构造函数()”来生成多个实例。但是,如果将类的构造函数设为私有的,外部类就无法调用该构造函数,也就无法生成多个实例。这时该类自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。 ``` /** * @purpose: 创建一个单例类 * Class Single */ class Single { /** * @var Object 保存类实例的静态成员变量 */ private static $_instance; /** * Single constructor. 私有的构造方法 */ private function __construct(){ echo 'This is a Constructed method;'; } /** * @purpose: 创建__clone方法防止对象被复制克隆 */ public function __clone(){ //E_USER_ERROR只能通过trigger_error($msg, E_USER_ERROR)手动触发。E_USER_ERROR是用户自定义错误类型,可以被set_error_handler错误处理函数捕获,允许程序继续运行。E_ERROR是系统错误,不能被set_error_handler错误处理函数捕获,程序会退出运行 trigger_error('Clone is not allow!',E_USER_ERROR); } /** * @return Single|Object 单例方法,用于访问实例的公共的静态方法 */ public static function getInstance(){ if(!(self::$_instance instanceof self)){ self::$_instance = new self; } return self::$_instance; } /** * @purpose: 测试方法 */ public function test(){ echo '调用方法成功'; } } ```