Java23种设计模式案例:单例模式(Singleton)

单例对象(Singleton)是一种经常使用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。java

一、适用场景

须要使得类的一个对象成为系统运行过程当中的惟一实例。设计模式

二、优势

    1)实例控制多线程

单例模式会阻止其余对象实例化其本身的单例对象的副本,从而确保全部对象都访问惟一实例。spa

     2)灵活性线程

由于类控制了实例化过程,因此类能够灵活更改实例化过程。设计

 

三、缺点

    1)开销code

虽然数量不多,但若是每次对象请求引用时都要检查是否存在类的实例,将仍然须要一些开销。能够经过使用静态初始化解决此问题。对象

    2)可能的开发混淆内存

使用单例对象(尤为在类库中定义的对象)时,开发人员必须记住本身不能使用new关键字实例化对象。由于可能没法访问库源代码,所以应用程序开发人员可能会意外发现本身没法直接实例化此类。开发

    3)对象生存期

不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类可以致使实例被取消分配,由于它包含对该实例的私有引用。在某些语言中(如 C++),其余类能够删除对象实例,但这样会致使单例类中出现悬浮引用。

四、代码示例

    1)关系图

    2)代码实现

        实现方式1:恶汉模式

//没有达到lazy loading的效果
class HungrySingleton{
    private static HungrySingleton singleton=new HungrySingleton();
    private HungrySingleton(){}
    public static HungrySingleton getInstance(){
        return singleton;
    }
}

        实现方式2:懒汉模式

class LazySingleton{
    private static LazySingleton singleton;
    private LazySingleton(){
    }
    public static LazySingleton getInstance(){
        if(singleton==null){
            singleton=new LazySingleton();
        }
        return singleton;
    }  
}

        实现方式3:静态内部类

//加载时不会初始化静态变量INSTANCE,由于没有主动使用,达到Lazy loading
class InternalSingleton{
    private static class SingletonHolder{
        private final static  InternalSingleton INSTANCE=new InternalSingleton();
    }  
    private InternalSingleton(){}
    public static InternalSingleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

        实现方式4:使用枚举

//《Effective Java》做者推荐使用的方法,优势:不只能避免多线程同步问题,并且还能防止反序列化从新建立新的对象
enum EnumSingleton{
    INSTANCE;
    public void doSomeThing(){
    }
}

        实现方式5:双重校验锁

//带有双重校验锁的单例模式
class LockSingleton{
    private volatile static LockSingleton singleton;
    private LockSingleton(){}
     
    public static LockSingleton getInstance(){
        if(singleton==null){
            synchronized(LockSingleton.class){
                if(singleton==null){
                    singleton=new LockSingleton();
                }
            }
        }
        return singleton;
    }   
}

        实现方式6:登记式单例

//相似Spring里面的方法,将类名注册,下次从里面直接获取。
class Singleton3 {
    private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
    static{
        Singleton3 single = new Singleton3();
        map.put(single.getClass().getName(), single);
    }
    //保护的默认构造子
    protected Singleton3(){}
    //静态工厂方法,返还此类唯一的实例
    public static Singleton3 getInstance(String name) {
        if(name == null) {
            name = Singleton3.class.getName();
            System.out.println("name == null"+"--->name="+name);
        }
        if(map.get(name) == null) {
            try {
                map.put(name, (Singleton3) Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
    //一个示意性的商业方法
    public String about() {    
        return "Hello, I am RegSingleton.";    
    }    
    public static void main(String[] args) {
        Singleton3 single3 = Singleton3.getInstance(null);
        System.out.println(single3.about());
    }
}
相关文章
相关标签/搜索