本篇文章主要介绍android开发中常用的单例模式和其中的几种写法,分析介绍在安卓开发中单例模式的优缺点。
一、常见的几种单例模式
首先来回顾一下几种常见的单例模式,分析一下个自的优缺点
1.懒汉式
//懒汉式单例类.在第一次调用的时候实例化自己
public class TestSingleton {
private TestSingleton() {}
private static TestSingleton single=null;
//静态工厂方法
public static TestSingleton getInstance() {
if (single == null) {
single = new TestSingleton();
}
return single;
}
}
优点:
避免了饿汉式的那种在没有用到的情况下创建事例,资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法。
缺点:
懒汉式在单个线程中没有问题,但多个线程同事访问的时候就可能同时创建多个实例,而且这多个实例不是同一个对象,虽然后面创建的实例会覆盖先创建的实例,但是还是会存在拿到不同对象的情况。
为了解决懒汉式造成的线程不安全以及可能会创建不同实例的问题,在此使用静态内部类的方式对懒汉式单例进行升级
public class TestSingleton {
private static class LazyHolder {
private static final TestSingleton instance = new TestSingleton ();
}
private TestSingleton (){}
public static final TestSingleton getInstance() {
return LazyHolder.instance;
}
}
这样既实现了线程安全,又避免了同步带来的性能影响。
优点
资源利用率高,不执行getInstance()不被实例,可以执行该类其他静态方法
缺点
第一次加载时反应不够快
2.饿汉式
//饿汉式单例类.在类初始化时,已经自行实例化
public class TestSingleton {
private TestSingleton() {}
private static final TestSingleton single = new TestSingleton ();
//静态工厂方法
public static TestSingleton getInstance() {
return single;
}
}
优点
1.线程安全
2.在类加载的同时已经创建好一个静态对象,调用时反应速度快
缺点
资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化
二、android中专有的单例模式
1.Activity中的单例
在android中,由于Activity不可以创建对象,所以要想给Activity设置单例,可以在Activity初始化的时候在onCreate()中对Activity,声明一个静态的变量,在Activity初始化时传递上下文。
public static MainActivity instance = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
instance = this;
}
此单例跟随Activity的生命周期,如果Activity死掉了 那么此单例也会死掉
2.自定义View中的单例
当我们写好了一个自定义View的类,一般情况下是需要把它加载到指定的Xml文件中,当这个Xml文件启动的时候,对应的自定义View就会加载,这个时候如果通过普通的饿汉式或懒汉式生命单例就会出现错误,所以就需要在自定义View初始化时的构造方法中声明单例,如下:
public static TestSingleView instance=null;
public TestSingleView (Context context) { super(context); this.context=context; instance=this; initView(); } public TestSingleView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.context=context; instance=this; initView(); }
此单例的生命周期跟随传递过来的上下文的生命周期。
三、单例模式的优缺点
1.优点
(1)由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁地创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。
(2)由于单例模式只生成一个实例,所以减少了系统的性能开销,当一个对象的产生需要比较多的资源时,比如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决。
(3)单例模式可以避免对资源的多重占用,例如一个写文件操作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作。
(4)单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如,可以设计一个单例类,负责所有数据表的映射处理。
2.缺点
(1)单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。
(2)单例对象如果持有Context,那么很容易引发内存泄露,此时需要注意传给单例对象的Context最好是Application Context。
(3)滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。