设计模式——单例模式
简单来说,单例模式,就是为了保证一个类仅仅只有一个实例,并且提供一个访问它的全局访问。
特点:
1.单例确保自己只有个实例(构造器私有:不被外部实例化,也不被集成)
2.单例必须自己创建自己的实例
3.单例类必须为其他对象提供唯一的实例
应用:
资源管理器,回收站,打印机资源,线程池,缓存,配置信息类,管理类,控制类,门面类,代理类通常被设计为单例类
如果应用多个类加载器又同时使用单例模式就会出现多个单例并存。
示例中一个饿汉模式单例,一个懒汉模式。
饿汉模式:
在单例类被加载时候,就实例化一个对象交给自己引用。
1 public class Singleton1 {
2 //饿汉式
3 private static Singleton1 singleton = new Singleton1();
4 private Singleton1(){}
5 public static Singleton1 getSingleton(){
6 return singleton;
7 }
8
9 }
懒汉模式,是指需要用的时候才去加载,如果开销比较大,希望用到时候才被加载,就用懒汉模式
1 public class Singleton2 {
2 //懒汉式
3 private static Singleton2 singleton;
4 private Singleton2() {
5 }
6 public static synchronized Singleton2 getInstance() {
7 if (singleton == null) {
8 singleton = new Singleton2();
9 }
10 return singleton;
11 }
12 }
同步一个方法的时候会造成执行效率下降,所以如果getInstance方法频繁使用就要重新考虑优化了
这里有个错误的实例
1 public class ErrorSingleton {
2 //单例模式错误示例
3 private ErrorSingleton errorSingleton = null;
4 private ErrorSingleton(){}
5
6 public ErrorSingleton getInstance(){
7 if (this.errorSingleton == null){
8 this.errorSingleton = new ErrorSingleton();
9 }
10 return this.errorSingleton;
11 }
12 }
我们看下错误实例中getInstance()判断null的部分,假如有线程A执行到这里申请分配内存,可能需要0.001微秒,在这0.001微秒内,线程B执行到判断isNull这个方法,这里到底会判断是否为空呢?
肯定是为空,于是线程B也往下走,这么就出现了两个ErrorSingleton实例了。此时就出问题了。这里要注意。
单例模式中还需要注意的问题,不要通过反射去获取单例对象,否则会实例化一个新对象。
测试例子
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> classType = Singleton3.class;
Constructor<?> c = classType.getDeclaredConstructor(null);
c.setAccessible(true);
Singleton3 s1 = (Singleton3) c.newInstance();
Singleton3 s2 = Singleton3.getInstance();
System.out.println(s1 == s2);
}
输出为false。
暂时就这么多。

浙公网安备 33010602011771号