作为对象的创建模式[GOF95],单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类.
Singleton模式是设计模式中最为简单,最为常见,最容易实现,也是最应该熟悉和掌握的模式.在公司招聘时单例模式是考的最多的模式.
问题:
如果你的系统中要创建一个唯一的对象, 请使用单例模式. 如数据库连接, 打印机的实例等.
单例类分为三种:饿汉式,懒汉式和登记式.
一. 饿汉式单例类
类图:
备注: - : 私有 + : 公有 à : create创建
源代码:
package com.DesignPatterns.Singleton;
/*
* 饿汉式单例类,不能被继承
*/
public class HungrySingleton {
/*
* Singleton类自己将自己实例化
* 此该类被加载时,静态变量instance 会通过调用私有构造函数被实例化
*/
private static final HungrySingleton instance = new HungrySingleton();
/*
* 私有构造函数防止此类被外界调用而产生多个实例
* 构造函数私有的类不能被继承
*/
private HungrySingleton(){}
public static HungrySingleton getInstance()
{
return instance;
}
}
二. 懒汉式单例类
类图:
源代码:
package com.DesignPatterns.Singleton;
/*
* 懒汉式单例类,不能被继承
*/
public class LazySingleton {
/*
* Singleton类自己将自己实例化
* 此该类被加载时,静态变量instance 会通过调用私有构造函数被实例化
*/
private static LazySingleton instance = null;
/*
* 私有构造函数防止此类被外界调用而产生多个实例
*/
private LazySingleton(){}
/*
* synchronized同步化以处理多线程环境
*/
synchronized public static LazySingleton getInstance()
{
if (instance == null)
instance = new LazySingleton();
return instance;
}
}
package com.DesignPatterns.Singleton;
/*
* 客户端代类
*/
public class Client {
public static void main(String[] args) {
HungrySingleton hungrysingleton = HungrySingleton.getInstance();
LazySingleton lazysingleton = LazySingleton.getInstance();
}
}
三. 登记式单例类
登记式单例类是针对上面两种单例类不能被继承的特点而设计的.本人认为并不常用,故略去详细描述, 具体实现参见<Java与模式>205页.
各个单例类的比较:
单从资源利用角度来讲, 饿汉式单例类较好; 从速度和反映时间来说懒汉式单例类较好.但是, 懒汉式单例类在实例化时, 必须处理好在多线程同时首次引用此类时的访问限制问题.特别是单例类在资源控制器在实例化时必然涉及资源初始化, 而资源初始化很有可能耗费时间, 这意味着出现多线程同时引用此类的几率变得较大.
<java与模式>作者认为饿汉式单例类更符合Java语言的特点.
书中209页属性管理器例子, 好.
如涉及到多线程的情况, 参见222页15.9节<双重检查成例>.