设计模式之单例(饿汉式、懒汉式、注册式枚举、容器)

   日期:2020-07-07     浏览:180    评论:0    
核心提示:设计模式一、饿汉式1. 简单的饿汉式2. 静态代码块写法3. 两种写法的总结二、懒汉式1. 简单的懒汉式2. 双重检查锁3. 静态内部类三、注册式1. 枚举2. 容器式

设计模式

    • 一、饿汉式
      • 1. 简单的饿汉式
      • 2. 静态代码块写法
      • 3. 两种写法的总结
    • 二、懒汉式
      • 1. 简单的懒汉式
      • 2. 双重检查锁
      • 3. 静态内部类
    • 三、注册式
      • 1. 枚举
      • 2. 容器式

一、饿汉式

1. 简单的饿汉式

	public class HungrySingleton {
	
	    private HungrySingleton(){
	
	    }
	
	    private final static HungrySingleton h = new HungrySingleton();
	
	    public  static HungrySingleton getInstance(){
	        return HungrySingleton.h;
	    }
	}

2. 静态代码块写法

public class HungrySingletonStatic {
	
	    private HungrySingletonStatic(){
	
	    }
	
	    private final static  HungrySingletonStatic h;
	
	    static {
	        h = new HungrySingletonStatic();
	    }
	
	    public static  HungrySingletonStatic getInstance(){
	        return HungrySingletonStatic.h;
	    }
	}

3. 两种写法的总结

饿汉式的这两种写法都是一样的,在类初始化的时候就创建了一个对象实例,当调用这个静态方法的时候返回的也是同一个对象实例,符合单例的设计思想。但是如果使用的单例比较多的情况下,使用这种方法在加载类的时候就会耗费很多资源,有些单例类可能暂时用不上,造成资源浪费。

二、懒汉式

1. 简单的懒汉式

public class LazySingleton {

    private LazySingleton(){}

    private static LazySingleton lazySingleton ;

    public static  LazySingleton getInstance(){
        if(lazySingleton == null){
            return new LazySingleton();
        }
        return lazySingleton;
    }
}

这里的懒汉式是线程不安全的,如果要线程安全需要枷锁,加锁之后代码如下

public class LazySingleton {

    private LazySingleton(){}

    private static LazySingleton lazySingleton ;

    public static synchronized LazySingleton getInstance(){
        if(lazySingleton == null){
            return new LazySingleton();
        }
        return lazySingleton;
    }
}

但是这种懒汉式加锁之后有性能问题

2. 双重检查锁

public class LazySingletonLock {

    private LazySingletonLock(){

    }

    private static LazySingletonLock lazySingleton ;

    public static  LazySingletonLock getInstance(){
        if(lazySingleton == null){
            synchronized (LazySingletonLock.class){
                if (lazySingleton == null){
                    return new LazySingletonLock();
                }
            }

        }
        return lazySingleton;
    }

}

双重检查锁解决了性能问题,但是代码量稍大。

3. 静态内部类

public class LazySingletonStatic {

    private LazySingletonStatic(){

    }
    
    private static class LazySingleton{
        private static final LazySingletonStatic l = new LazySingletonStatic();
    }

    public static  LazySingletonStatic getInstance(){
        return LazySingleton.l;
    }

}

这里用了Java的类加载机制,静态内部类只有使用的时候才会被加载,但是使用反射强制获取构造方法的时候就会破环单例,使用反射获得的构造方法可以创建无数个实例。

三、注册式

1. 枚举

public enum EnumSingleton {
    INSTANCE;
    private Object data;
    public Object getObj(){return data;}

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance(){
        return INSTANCE;
    }
}

如果使用反射强制获取枚举的构造方法并且创建实例的时候,枚举的构造方法会抛出一个异常
在加载的时候就会实例化,内存浪费,又变成饿汉式。

2. 容器式

public class Container {

    private Container(){}

    //hashMap在初始化的时候,会有多个KEY相同,但是值不相同的数据,存储时一个KEY可能存入两个value的情况
    private static Map<String,Object> singleton = new HashMap<>();

    public static void putInstance(String key,Object object){
        if( key.length() > 0 && object != null){
            if(!Container.singleton.containsKey(key)){
                singleton.put(key,object);
            }
        }
    }

    public static Object getInstance(String key){
        return singleton.get(key);
    }
}

是枚举单例的优化版本,解决了可能造成内存浪费的问题,但是引发了线程安全问题,Spring IOC容器使用的这种方式。

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服