我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情
简述
单例模式是我们开发中最常用到的一种设计模式。
单例模式的优点:
- 内存中只有一个对象实例,节省内存空间;
- 避免频繁创建实例带来的性能消耗;
- 提供一种全局访问入口,比如读取配置信息;
单例模式的缺点:
- 一般静态类不提供接口实现、抽象方法等功能,扩展能力差,修改的话只能在这个单例类里面修改。
- 由于静态模式使用了static全局变量,所以涉及到生命周期的引用很容易引起内存泄漏。比如传入了一个activity。这个时候我们需要传入的是跟static生命周期一样长的application context,否则就不要使用单例模式。比如像Dialog对话
单例模式适用场景:
6. 对象需要保存一些状态信息;
7. 避免多重读写操作。比如如果多个实例读取了同一资源文件,后续涉及到对这个资源文件写同步的操作。
单例模式
单例模式的实现由很多种,这边说一种最常用的实现。直接看代码说话:
public class SingletonDemo {
private static volatile SingletonDemo sInstance = null;
private SingletonDemo() {
}
public static SingletonDemo getInstance () {
if (sInstance == null) {
synchronized(SingletonDemo.class){
if (sInstance == null) {
sInstance = new SingletonDemo();
}
}
}
return sInstance;
}
public void printSomething() {
System.out.println("this is a singleton");
}
}
这种写法的好处:
- 构造函数private,不能直接new对象,保证通过getInstance渠道创建;
- 由于不能直接new对象,所以getInstance方法必须是一个static方法;而静态方法不能访问非静态成员变量,所以这个实例变量也必须是static的。
- 双重检查锁,使用volatile关键字,重排序被禁止,所有的写(write)操作都将发生在读(read)操作之前。
说到单例模式,就不得不提到静态类。
静态类
静态类大家应该都很熟悉,用static修饰的方法或者变量,直接调用,方便快捷。
public class StaticDemo {
public static void printSomething() {
System.out.println("this is a static");
}
}
这是一个最简单的静态类,提供一个静态方法printSometing。
静态类的优点:
- 静态类的方法直接调用即可,无需new一个实例对象。
- 静态类的性能较优,因为静态类的方法是在编译期间就绑定了。
静态类的缺点:
- static方法不能被override,没有扩展性;
- 接上述,单例做不到懒加载;
单例和静态类的选择
单例是表现类,静态类是表现方法。
1、如果需要类的扩展能力的时候比如Override,选择单例模式;
2、如果类比较重,需要考虑懒加载的时候,选择单例模式;
3、如果有状态信息维护需求,选择单例模式;
4、如果有资源文件访问需求,选择静态类;
5、如果需要将一些方法集中在一起,选择静态类;