设计模式(一)单例模式(Singleton)

介绍

特点:只有一个实例对象存在(因为被 private 修饰)。

应用场景:  
(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如日志文件,应用配置。
(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。

实现方法(三种):

名称 特点 优点 缺点
饿汉法 在加载类的时候就会创建类的单例,并保存在类中 代码简单 无法延迟加载,线程不安全,可被人使用反射强行调用构造器
懒汉法 不在系统加载时就创建类的单例,而是在第一次使用实例的时候再创建,为保证线程安全,加 synchronized 关键字修饰 延迟加载,加 synchronized 关键字后实现线程安全 效率低下,可被人使用反射强行调用构造器
双重加锁机制 双重判断,先判断单例是否存在,只对不存在的单例进行同步操作 延迟加载,JDK 1.5 后线程安全,效率较懒汉高 使用 volatile 关键字(修饰的变量不会被本地线程缓存,读写操作直接操作内存决定,会屏蔽虚拟机中的优化代码,运行效率低下)可被人使用反射强行调用构造器
静态内部类法 将 Singleton 实例放到一个静态内部类中,静态内部类只会加载一下,Singleton 只实例化一次 延迟加载和线程安全 需要额外的工作(Serializable、transient、readResolve())来实现序列化,否则每次反序列化一个序列化的对象实例时都会创建一个新的实例,可被人使用反射强行调用构造器
枚举写法(最优) 枚举 线程安全,防止反射强行调用构造器,自动序列化,防止反序列化时自动创建对象 Android平台不推荐使用

饿汉法

class EHSingleton {
    private static EHSingleton ehSingleton = new EHSingleton();
    private EHSingleton() {}
    public static EHSingleton getSingleton() {
        return ehSingleton;
    }
}

懒汉法

class LHSingleton {
    private static LHSingleton lhSingleton = null;
    private LHSingleton() {}
    private static synchronized LHSingleton getLhSingleton() {
        if (lhSingleton == null) {
            lhSingleton = new LHSingleton();
        }
        return lhSingleton;
    }
}

双重加锁机制

class Singleton {
    private static volatile Singleton singleton = null;
    private Singleton() {}
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

静态内部类法

class staticSingleton {
    private static class Holder {
        private static staticSingleton staticSingleton = new staticSingleton();
    }
    private staticSingleton() {}
    public static staticSingleton getSingleton() {
        return Holder.staticSingleton;
    }
}

枚举法

enum enumSingleton {
    INSTANCE;
    private String name;
    public  String getName(){
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

总结:

不同的环境可根据具体情况选择合适的单例模式,但尽量要实现单例的三个要点:
1、保证线程安全
2、延迟加载
3、序列化与反序列化安全
可优选“枚举写法”,JDK 1.5 之前 不适合先选择“双重加锁写法”,Android平台不适宜选择“枚举”。


THE END

你可能感兴趣的:(系统架构)