一、定义
确保某一个类只有一个实例,而且自行实例化并乡整个系统提供这个实例。
二、使用场景
确保某个类有且只有一个对象的场景,避免产生多个对象消耗多个资源。或者某些类占用太多的资源,不适合创建多个对象的情况;例如:数据库、IO访问,
android中使用单例模式的类:ImageLoader
三、单例的类图
- 角色介绍
- Client 客户端类
- Singleton 单例类
- 实现的关键点
- 构造方法设置成为私有的private;
- 通过静态方法或枚举类型返回单例对象;
- 确保线程安全;
备注:单例模式的类,有且只能有一个入口,注意尽量不要在单例模式中使用参数,尤其是传人类对象,会导致单例对象持有没必要的引用,可能导致内存泄漏。
四、代码实例
1.饿汉模式
public class Person {
private static final Person instance = new Person();
private Person() {
}
public static Person getInstance() {
return instance;
}
}
最简单的单例模式,但是线程不安全。
2.懒汉模式
public class Person {
private static Person instance;
private Person() {}
public static synchronized Person getInstance() {
if (instance == null) {
instance = new Person();
}
return instance;
}
}
可以保证线程安全问题,但是每一次使用getInstance()方法都会进行同步,而且第一次加载时需要进行实例化,反应稍慢;
3.Double Check Lock(DCL)实现单例模式
public class Person {
private static volatile Person instance;
private Person() {}
public static Person getInstance(){
if(instance == null){
synchronized (Person.class){
if(instance == null){
instance = new Person();
}
}
}
return instance;
}
}
第一次判空是为了避免不必要的重复,
第二次判空是为了在null情况下创建实例;
通过俩次检测初始化对象实例,优点是仅在需要的时候会创建实例,资源利用率高,缺点由于java的内存模型的原因偶尔会失败;推荐使用volatile关键字,将对像直接写入主内存,会影响性能,但是会保证程序的准确性。
4.静态内部类实现单例模式
public class Person {
private static volatile Person instance;
private Person() {}
public static Person getInstance(){
return PersonHolder.instance;
}
//静态内部类
private static class PersonHolder {
private static final Person instance = new Person();
}
}
优点:
1)第一次加载Person不会初始化;
2)第一次加载getInstance()导致虚拟机加载PersonHolder类,才会进行类的初始化;
3)可以保证线程安全,以及单例的唯一性;
4)延迟了类的实例化,推荐使用该方法。
五、android源码中的实现
- 1.Context
- 2.LayoutInflater
- 3.PolicyManager