一、单例模式介绍
单例模式是我们在开发中经常用到的一种设计模式。单例模式创建的类在当前进程中只有一个实例,并有一个访问它的全局入口。
1. 单例模式的优点
- 内存中只有一个对象实例,节省了内存空间。
- 避免了频繁创建实例带来的性能消耗。
- 提供了一种全局访问入口,例如读取配置信息。 ·
2. 单例模式的缺点
- 一般静态类不提供接口实现、抽象方法等功能,扩展能力差,修改的话只能在这个单例类里面进行。
- 由于静态模式使用了static全局变量,所以涉及生命周期的引用,这样很容易引起内存泄漏。例如传入了一个Activity类。这个时候我们需要传入的是跟static生命周期一样长的Application Context,否则就不要使用单例模式,例如像Dialog对话一样。
3. 单例模式适用场景
- 对象需要保存一些状态信息。
- 避免多重读写操作。例如多个实例读取了同一资源文件,后续涉及对这个资源文件写入同步的操作。
二、 单例模式实现
单例模式的实现有很多种,这里展示一种最常用的实现。代码如下:
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)操作之前。
除了使用上述传统的方式创建单例模式,我们还可以通过枚举实现:public enum SingletonDemo { INSTANCE; }
然后直接通过SingletonDemo.INSTANCE调用,比传统实现方便多了。枚举实现的单例模式不但能保证线程安全,而且能防止反序列化时重新创建新的对象。
说到单例模式,就不得不提到静态类。
三、 静态类
静态类用static修饰的方法或者变量,可以直接调用,方便快捷。
public class StaticDemo {
public static void printSomething() {
System.out.println("this is a static");
}
}
这是一个最简单的静态类,提供一个静态方法printSomething()。
1. 静态类的优点
- 静态类的方法直接调用即可,无须new一个实例对象。
- 静态类的性能较好,因为静态类的方法是在编译期间就绑定了的。
2. 静态类的缺点
- 静态类方法不能被Override,没有扩展性。
- 静态类做不到懒加载。
四、单例和静态类的选择
单例表现的是类,静态类表现的是方法。
- 如果需要类的扩展能力,例如Override,选择单例模式。
- 如果类比较重,需要考虑懒加载,选择单例模式。
- 如果有状态信息维护需求,选择单例模式。
- 如果有资源文件访问需求,选择静态类。
- 如果需要将一些方法集中在一起,选择静态类。








网友评论