单例模式是23种设计模式中最简单、最常见的一种,也是各个公司面试题中必考的设计模式之一,是程序猿必备掌握的。
单例模式(Singleton Pattern):
确保某个类只有一个对象。单例类的构造器是私有的(private),避免外界利用构造器直接创建出任意多的实例。由于构造器是private的,因此单例类是不能被继承。
特点:
1>、单例类只能有一个实例。
2>、单例类必须自己创建自己的唯一实例。
3>、单例类必须给所有其他对象提供这一实例。
单例模式,可以形象的比作"一山不容二虎",如:计算机系统中,我们只需要他有一个唯一的实例在工作。无论一个电脑连接了多少台打印机,但是它的后台处理程序只有一个唯一的实例在工作,这样才不会出现混乱的交错情况。
单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。
1、饿汉式单例
是一种典型的空间换时间的方式,在类进行加载时,我们静态实例对象就完成了实例化操作。操作时因为加载时已经实例化过了,操作速度会变快。但是因为类加载时这个对象就已经存在了,它的生命周期较长,占用空间。
package 单例模式;
/**
* 饿汉式单例:自己将自己实例化
* 在这个类被加载时,静态变量instance会被初始化,此时类的私有构造器被调用,这时单例类的唯一实例就被创建了。
* @author xcbeyond
* @date 2012-5-1 上午11:56:26
*/
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
//私有构造器
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return instance;
}
}
2、懒汉式单例
与饿汉式单例不同的是,懒汉式单例类在第一次被引用时将自己实例化。如果加载器是静态的,那么在懒汉式单例类被加载时不会将自己实例化。
package 单例模式;
/**
* 懒汉式单例
* @author xcbeyond
* @date 2012-5-1 下午12:23:54
*/
public class LazySingleton {
private static LazySingleton instance = null;
//私有构造器
private LazySingleton(){
}
//静态工厂方法,返回此类的唯一实例
synchronized public static LazySingleton getInstance () {
if(instance == null ) {
instance = new LazySingleton();
}
return instance;
}
}
3、登记式单例
为了克服饿汉式单例类和懒汉式单例类不可继承的缺点,于是引入了登记式单例类。
package 单例模式;
import java.util.HashMap;
/**
* 登记式单例类:克服了饿汉式和懒汉式单例类的不可继承的缺点。
* @author xcbeyond
* @date 2012-5-1 下午12:35:23
*/
public class RegisterSingleton {
private static HashMap reg = new HashMap();
static {
RegisterSingleton x = new RegisterSingleton();
reg.put(x.getClass().getName(), x);
}
//保护的默认构造器
protected RegisterSingleton () {
}
//静态工厂方法,返回此类唯一的实例
public static RegisterSingleton getInstance(String name) {
if(name == null) {
name = "RegisterSingleton";
}
if(reg.get(name)==null) {
try{
reg.put(name, Class.forName(name).newInstance());
}catch(Exception e) {
System.out.println("Error happened");
}
}
return (RegisterSingleton)reg.get(name);
}
}
饿汉PK懒汉
饿汉式,类加载时进行了对象的实例化创建,即使多个进程并发操作,访问的实例也是唯一的,饿汉式线程安全。
懒汉式,第一次使用才会实例化,多个线程并发操作时,由于时间片的切换,可能导致线程风险。