软件设计 单例模式
一、一个类只能有一个实例(对象);
二、单例类必须自行创建这个实例(对象),单例类必须构造方法私有化;
三、单例类必须自行向整个系统提供这个实例。
1.饿汉式单例(时间少)是最普通的单例模式写法,由于在类加载时就创建对象,保证了线程的安全。这种方式比较常用,但容易产生垃圾对象,对空间的消耗较大。
public class Singleton {
/**
* 单例模式的核心,无参构造方法私有化
*/
private Singleton() {
}
/**
* INSTANCE 实例的意思
* 用于全局引用的唯一单例对象,在一开始就创建好
*/
private final static Singleton INSTANCE = new Singleton();
/**
* 获取全局唯一的单例对象
* @return 实例对象
*/
public static Singleton getInstance() {
return INSTANCE;
}
}
这种方式最大的问题就是浪费内存,因为创建的对象程序不一定用得到,如果创建了没用到,就是一种浪费。这种方式由于不存在线程安全问题, 因此不用加锁,效率较高,以空间换时间
2.懒汉式单例(空间少)就是在类加载时不创建对象,用到的时候才创建对象。
public class Singleton {
/**
* 单例模式的核心,构造方法私有化
*/
private Singleton() {
}
/**
* 在一开始先不进行对象创建
*/
private static Singleton INSTANCE;
/**
* 获取全局唯一的单例对象
* @return 单例对象
*/
public static Singleton getInstance() {
// 如果实例为空,那么就进行创建,不为空说明已经创建过了,就直接返回,保证单例
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
这种方式最大的问题就是在多线程情况下不安全
通过 双重检测锁实现(方式一),静态内部类实现(方式二),
上面两种方式实现的话,反射可以破坏单例。
3.枚举单例(枚举实现是最完美的单例模式)
public enum Singleton {
/**
* 单例对象
*/
INSTANCE
}
但因为必须 Java 1.5 及之后的版本才支持这种方式,所以还没有被广泛采用,但这确实是实现单例模式的最佳方法和最简单方法,也正验证了单例模式是最简单的设计模式。
单例模式的优缺点:
优点
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。(节约资源)
缺点
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
单例模式的使用场景:
1、要求生产唯一序列号。
2、Web 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。