安卓单例模式

来源:互联网 发布:手机淘宝怎样付款 编辑:程序博客网 时间:2024/06/02 04:14

单例模式:应用最广的模式之一,设计模式如果你听说过一个,那么一定是这个(可能是初级工程师唯一会的一种设计模式躺枪)

单例,顾名思义,整个内存系统中只有这一个实例化的对象
应用场景:避免多个产生多个对象消耗过多的资源(尽量不要找小三…)
什么消耗资源过多呢?IO流操作,数据库访问等
单例

  • 传统一般菜鸟知道的两种
/** * 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());    }}
/** * 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;    }}

注意 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();    }}

优化到头了吧,`? 进阶

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

不禁惊呼,还可以这么写啊! 枚举类型 并且保证了 反序列化 的时候,实例也唯一.而之前的写法 都要重写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);    }}

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

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

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

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

优点:

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

缺点:

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

参见android源码设计模式

1 0
原创粉丝点击