Java设计模式<单例模式>
意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点
优点
- 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存
- 避免对资源的多重占用(比如写文件操作
缺点
- 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化
样例
public class SingleObject {
private static SingleObject instance = new SingleObject();
private SingleObject() {
}
public static SingleObject getInstance(){
return instance;
}
public void showMsg(){
System.err.println("我是单例的,我只有一个对象");
}
}
public class DemoMain {
public static void main(String[] args) {
SingleObject singleObject = SingleObject.getInstance();
singleObject.showMsg();
}
}
consle
我是单例的,我只有一个对象
单例模式的几种实现方式
- 懒汉式,线程不安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 懒汉式,线程安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 登记式/静态内部类
这种方式同样利用了 classloder 机制来保证初始化 instance 时只有一个线程,这种方式是 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有显示通过调用 getInstance 方法时,才会显示装载 SingletonHolder 类,从而实例化 instance。想象一下,如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。这个时候,这种方式相比第 3 种方式就显得很合理
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}