安卓单例模式

  • 传统一般菜鸟知道的两种
/**
 * Created by lcqbug on 2016/6/27.
 * 饿汉式
 */
public class Singletonhungry {
    private static Singletonhungry singletonhungry = new Singletonhungry();//属性就new了个对象出来,缺点,类加载之初,就开辟了对象空间,占用了内存
    private Singletonhungry (){

    }

    /**
 * 提供一个静态方法,导致 属性也要 static
 * @return
 */
    public static Singletonhungry getInstance(){
        return singletonhungry;
    }
    public void doSometing(){
        Log.e("lc--",singletonhungry.toString());
    }
}
  • 1
/**
 * Created by lcqbug on 2016/6/27.
 */
public class Singletonlazy {
    private static  volatile Singletonlazy singletonlazy;//volatile 关键字可以让编译器按部就班的执行代码,不会跳过和省略.(JDK1.5之后)
    private Singletonlazy(){

    }

    /**
 * 相比饿汉式,方法调用的时候才实例化对象.可是每次调用都要同步,开销较大,于是对其做改进
 * @return
 */
    public static synchronized Singletonlazy getInstance(){
// if (singletonlazy == null){
// return new Singletonlazy();
// }else {
// return singletonlazy;
// }
        if (singletonlazy == null){
            singletonlazy = new Singletonlazy();
        }
        return singletonlazy;
    }

    /**
 * 改进后的懒汉式,DCL机制(double check lock)
 * 一定程度上解决了资源消耗,多余的同步,线程安全的问题.但某些特别的情况下还是会失效(见 Java 并发编程实践),不建议使用,但这种方式应用场景还是蛮多的
 * @return
 */
    public static Singletonlazy getSingletonlazy(){
        if (singletonlazy == null){
            synchronized (Singletonlazy.class){
                if (singletonlazy == null){
                    singletonlazy = new Singletonlazy();
                }
            }
        }
        return singletonlazy;
    }

    /**
 * http://www.javalobby.org/java/forums/t17491.html
 * @return
 * @throws ObjectStreamException
 */
    private Object readResolve() throws ObjectStreamException{
        return singletonlazy;
    }

}
  • 1

注意 Dcl机制 和 volatile 关键字的使用.但dcl 也不是万能 的,推荐方式呢?
更上一层楼的写法.妙“

public class Singletoninner {
    private Singletoninner (){}
    private static Singletoninner getSinleoninner(){
        return SingletonHolder.singletoninner;
    }

    private static class SingletonHolder {
        private static final Singletoninner singletoninner = new Singletoninner();
    }
}
  • 1

优化到头了吧,`? 进阶

/**
 * Created by lcqbug on 2016/6/27.
 *
 * 亮瞎me24氪金狗眼的写法,简单至极,并且任何情况下 对象唯一...
 */
public enum  SingletonEnum {
    SINGLETON_ENUM;
    public void doSomething(){
        Log.e("lc--","enum---");
    }
}
  • 1

不禁惊呼,还可以这么写啊! 枚举类型 并且保证了 反序列化 的时候,实例也唯一.而之前的写法 都要重写readResolve()方法

还有吗?学无止境

/**
 * Created by lcqbug on 2016/6/27.
 * 前面已经让人叹服了,还没完,来看一个脑洞大开的 写法
 */
public class SingletonManager {
    private static Map<String,Object> objectMap  = new HashMap<>();
    private SingletonManager(){

    }
    public static void registerService(String key,Object instance){
        if (!objectMap.containsKey(key)){
            objectMap.put(key,instance);
        }
    }
    public static Object getService(String key){
        return objectMap.get(key);
    }
}
  • 1

这种写法可以管理多种类型的单例,并且隐藏了具体实现.

至此,单例完结.畅快淋漓

总结: 不管哪种,共同点 都是 构造方法,属性 私有化,提供一个static的方法给外界调用.还要保证线程安全,防止反序列化导致重新生成实例对象等问题.

选择哪种方式取决于项目本身,考虑 并发环境,JDK版本是否过低,单例资源的消耗等.

优点:

  1. 减小内存开销
  2. 较小性能开销
  3. 避免资源多重占用
  4. 可以设置全局访问点,优化和共享资源访问

缺点:

  1. 扩展 只能改 这个 单例类,不可能 通过继承的方式去修改了
  2. 单例对象如果持有Context,很容易内存泄露,此时传递给 单例对象的Context最好是ApplicationContext

参见android源码设计模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若♡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值