Java(Android)设计模式-单例模式

原文地址为: Java(Android)设计模式-单例模式

概述

回顾一下之前写的单例模式文章,太过于繁琐,而且没有切中单例模式的要害,因此借机重写一下单例模式的具体实现方式。
首先,单例模式一共有5种实现方式,分别是:
  • 饿汉式
  • 懒汉同步锁式
  • 懒汉双重校验锁式
  • 懒汉静态内部类式
  • 枚举类式

我们以改造一个日志类为例,来介绍一下单例模式的5种实现。

改造前的日志类源码如下:
public class LogUtil {	public final int DEBUG = 0;
public int level = DEBUG;

public void debug(String msg) {
if (DEBUG >= level) {
System.out.println(msg);
}
}
}

在介绍几种单例模式之前,我们以这个LogUtil类为例,说明一下为什么要使用单例模式?
是因为单例模式可以做到:1. 减少内存开销,因为只有一个类实例; 2. 避免对资源的多重占用; 3. 实现了资源的全局访问.

饿汉式

public class LogUtil {    private static LogUtil sInstance = new LogUtil();    private LogUtil() {    }    public static LogUtil getInstance() {        return sInstance;    }    public final int DEBUG = 0;    private int level = DEBUG;    public void debug(String msg) {        if (DEBUG >= level) {            System.out.println(msg);        }    }    public static void main(String[] args) {        LogUtil logUtil = LogUtil.getInstance();        logUtil.debug("haha");    }}

饿汉式是单例实现最简单的方式,因此它的优点也是实现简单,同样缺点也非常明显,做不到延迟加载。当单例类调用不是特别频繁且存在大量资源占用时,使用饿汉模式会导致单例类在程序初始时就被实例化,浪费系统资源。
针对饿汉式这种存在资源浪费的缺点,因此单例又衍生了几种懒汉式的实现。

懒汉同步锁式

因为懒汉模式是延迟加载,需要考虑到线程安全,因此同步锁是使用synchronized对整个函数加Class锁来保证线程安全.
public class LogUtil {    private static LogUtil sInstance;    private LogUtil() {    }    public synchronized static LogUtil getInstance() {        sInstance = new LogUtil();        return sInstance;    }    public final int DEBUG = 0;    private int level = DEBUG;    public void debug(String msg) {        if (DEBUG >= level) {            System.out.println(msg);        }    }    public static void main(String[] args) {        LogUtil logUtil = LogUtil.getInstance();        logUtil.debug("haha");    }}
synchronized锁住整个函数,对多线程访问单例类时会造成排队等待的情况,归根节点的原因还是锁粒度太粗,因此又衍生出了懒汉双重校验锁式。

懒汉双重校验锁式

双重校验就是通过volatile关键字和减少synchronized的范围来减少多线程的竞争.
public class LogUtil {    private volatile static LogUtil sInstance;    private LogUtil() {    }    public static LogUtil getInstance() {        if (sInstance == null) {            synchronized (LogUtil.class) {                if (sInstance == null) {                    sInstance = new LogUtil();                }            }        }        return sInstance;    }    public final int DEBUG = 0;    private int level = DEBUG;    public void debug(String msg) {        if (DEBUG >= level) {            System.out.println(msg);        }    }    public static void main(String[] args) {        LogUtil logUtil = LogUtil.getInstance();        logUtil.debug("haha");    }}
双重校验锁在JDK1.5版本存在Bug,当然Android默认都是基于JDK1.6及以上版本编译,不存在该问题。为了兼容JDK1.5且简化代码实现,因此有衍生了静态内部类的懒汉式.

懒汉静态内部类式

因为是静态内部类,所以可以做到线程安全,且延迟加载。
public class LogUtil {    private static class SingletonHolder {        public static LogUtil sInstance = new LogUtil();    }    private LogUtil() {    }    public static LogUtil getInstance() {        return SingletonHolder.sInstance;    }    public final int DEBUG = 0;    private int level = DEBUG;    public void debug(String msg) {        if (DEBUG >= level) {            System.out.println(msg);        }    }    public static void main(String[] args) {        LogUtil logUtil = LogUtil.getInstance();        logUtil.debug("haha");    }}

枚举类式

Effective Java中推荐了一种更优雅的实现,就是使用枚举类来实现单例类。
枚举除了线程安全和防止反射调用构造器外,还提供自动序列化机制,防止反序列化时自动创建新的对象.
public enum LogUtil {    INSTANCE;    public final int DEBUG = 0;    private int level = DEBUG;    public void debug(String msg) {        if (DEBUG >= level) {            System.out.println(msg);        }    }    public static void main(String[] args) {        LogUtil logUtil = LogUtil.INSTANCE;        logUtil.debug("haha");    }}


转载请注明本文地址: Java(Android)设计模式-单例模式

猜你喜欢

转载自blog.csdn.net/dearbaba_8520/article/details/80838803
今日推荐