我眼中的单例模式

来源:互联网 发布:怎么用c语言编写软件 编辑:程序博客网 时间:2024/05/16 10:23

单例模式是一中很常用的设计模式,写代码的过程经常有用到.

什么情况下需要单例模式

当你只想持有一个实例的时候.这个实例的生命周期是跟随进程的,一旦初始化就常驻内存,并且只有一个实例.
举个例子,如果是一个安卓的工程,Application这个类就是单例的,我只会需要一份.如果是一个普通的任意一个应用,为了表达平台信息的等,这个类也不太可能多处实例化,一般也只需要一个.
单例的坏处在于会占这内存不放.如果需要释放内存,还要手动的操作.

单例模式的示例

1.先上一个最简单的单例模式,这个模式也是非线程安全的

       public class SingleInstance {         //private 保证了不能在类的外部来构造一个实例         //static 保证了与类相关的,只能有一份          private static SingleInstance  sSingleInstance;          private String mName;          private SingleInstance(String name) {             mName = name;         }        public static SingleInstance getInstance() {            if (null == sSingleInstance) {                sSingleInstance = new SingleInstance("非线程安全 饱汉(也叫懒初始化) 单例模式");           }         return sSingleInstance;       }}

2.例子1中的单例,当面临多线程访问的时候,会有初始化的问题.下面给出一个最简单粗暴的线程安全的例子

          private static SingleInstance  sSingleInstance;          private String mName;          private SingleInstance(String name) {             mName = name;         }         //对,与你想的一样,就是加一个同步的关键字        public static synchronized SingleInstance getInstance() {            if (null == sSingleInstance) {                sSingleInstance = new SingleInstance("非线程安全 饱汉(也叫懒       初始化) 单例模式");           }         return sSingleInstance;       }

3.例子2中的同步关键字,锁的范围太大,就有了改进版

  //如果是下面这样的加锁方式,是一定要有volatile关键字的    private static volatile SafeSingleInstance sSingleInstance;    private String mName;    private SafeSingleInstance(String name) {        mName = name;    }    //可以直接把整个方法锁住,不过代价比较大,这种方法是直接锁getInstance方法的改良版    public static SafeSingleInstance getInstance() {        if (null == sSingleInstance) {            synchronized (SafeSingleInstance.class) {                if (null == sSingleInstance) {                    sSingleInstance = new SafeSingleInstance("线程安全 双重检查的 单例模式");                }            }        }        return sSingleInstance;    }    public String getName() {        return mName;    }

4.与例子3相似的,还有一种通过static方法来完成的线程安全

private static SafeSingleInstance2 safeSingleInstance2;    private String mName;    private SafeSingleInstance2(String name) {        mName = name;    }    //实现这种方式的原理是,因为在类的初始化过程中对于一些static的类型的初始化时,系统级别的有加上锁的,不需要再显示的加上锁    private static class  SafeSingleInstanceHolder {        public static SafeSingleInstance2 holder = new SafeSingleInstance2("线程安全 初始化方式改造 单例模式");    }    public static SafeSingleInstance2 getInstance() {        return SafeSingleInstanceHolder.holder;    }    public String getName() {        return mName;    }

5.以上的例子都是比较友善的方式,只有当你需要使用的时候才会加载.也有一种暴力的线程安全,就是一旦类加载就初始化,也叫做饿汉单例模式

//这种单例模式的坏处在于,只要加载类,类就完成了实例化,不是一个友好的设计    private static SafeSingleInstance1  sSingleInstance = new SafeSingleInstance1("线程安全 饿汉 单例模式");    private String mName;    private SafeSingleInstance1(String name) {        mName = name;    }    public static SafeSingleInstance1 getInstance() {        return sSingleInstance;    }    public String getName() {        return mName;    }

为了更好的查看,以代码的方式进行了记录.详情请查看DesignPattern中的 com.arron.pattern.single下的内容.戳我查看详情

原创粉丝点击