单例模式-DesignPattern

147 阅读2分钟

一、介绍

单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的必须保证只有一个实例存在。

单例模式保证了系统只存在一个实例,节省内存资源。减少了重复创建,提高了性能。

二、分类

  • 饿汉模式:指全局的单例实例在类装载时构建
  • 懒汉模式:指全局的单例实例在第一次被使用时构建。

三、实现方式

  • 私有化构造函数
  • 提供静态获取单例方法

四、代码实现

1、饿汉模式:

public class App {
    public static volatile App instance = new App();
    private App(){}

public static App getInstance() {
    return instance;
}}

2、懒汉模式:

public class App {private App() {

}

public static volatile App   instance;

public static synchronized App getInstance() {
    if (instance == null) {
        synchronized (App.class) {
            if (instance == null) {
                instance = new App();
            }
        }
    }
    return instance;
}
}

五、懒汉模式的演进

1、判空检验

这种在多线程情况下,容易产生多个实例

public class App {public static App instance ;

public static App getInstance(){
    if(instance == null){
        instance = new App();
    }
    return instance;
}
}

2、方法加锁

这种方式,锁力度较大,性能开销大

public class App {
public static App instance;

private App(){

}

public static synchronized App getInstance() {
    if (instance == null) {
        instance = new App();
    }
    return instance;
}}

3、双重检验锁

这种方式在多线程情况下也能保证高性能,但是由于JVM创建对象过程不是原子操作,存在指令重排,容易产生报错。

public class App {

    private App() {

    }

    public static App instance;

    public static synchronized App getInstance() {
        if (instance == null) {
            synchronized (App.class) {
                if (instance == null) {
                    instance = new App();
                }
            }
        }
        return instance;
    }

}

4、双重检验锁+ volatile

即保证多线程高性能,也可以避免指令重排

public class App {
private App() {

}

public static volatile App instance;

public static synchronized App getInstance() {
    if (instance == null) {
        synchronized (App.class) {
            if (instance == null) {
                instance = new App();
            }
        }
    }
    return instance;
}
}

六、Android源码中的单例模式

InputMethodManager.java

public final class InputMethodManager {
      static InputMethodManager sInstance;
      public static InputMethodManager getInstance() {       synchronized (InputMethodManager.class) {
            if (sInstance == null) {
                try {
                    sInstance = new InputMethodManager(Looper.getMainLooper());
                } catch (ServiceNotFoundException e) {
                    throw new IllegalStateException(e);
                }
            }
            return sInstance;
        }
    }      
}


android.util.Singleton.java

public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}