设计模式之单例模式

设计模式之单例模式

一、单例模式

1.单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实列,并提供
一个全局访问点。
2.隐藏其所有的构造方法
3.属于创建型模式。

1. 学习单例模式应掌握什么?

1.掌握单例模式的应用场景
2.掌握IDEA环境下的多线程调试方式
3.掌握保证线程安全的单例模式策略
4.掌握反射暴力攻击单例解决方案及原理分析
5.序列化破坏单例的原理及解决方案
6.掌握常见的单例模式写法

2. 适用场景

1. 确保任何情况下都绝对只有一个实例

3.缺点

1. 没有接口,扩展困难
2. 如果要扩展单例对象,只有修改代码,没有其他途径

二、常见的单例模式写法

1.饿汉式单例
2.懒汉式单例
3.注册时单例
4.ThreadLocal单例

1. 饿汉式单例

/**
 * 饿汉式单例
 * 优点:执行效率高,性能高,未加任务锁
 * 缺点:在某些情况下造成内存浪费。
 *
 */
public class HungryStaticSingleton {

    // 先静态后动态
    // 先上后下
    // 先属性后方法
    private static final HungryStaticSingleton hungrySingleton;

    static{
        hungrySingleton = new HungryStaticSingleton();
    }

    public HungryStaticSingleton() {
    }

    public static HungryStaticSingleton getInstance(){
        return hungrySingleton;
    }
}

2. 懒汉式单例

1. 简单模式的懒汉式单例
/**
 * 懒汉式单例()
 * 优点:节省了内存,线程安全
 * 缺点:性能低
 *
 */
public class LazySimpleSingleton {

    private static LazySimpleSingleton instance;

    public LazySimpleSingleton() {
    }

    public synchronized static LazySimpleSingleton getInstance(){
        if(null == instance){
            instance = new LazySimpleSingleton();
        }
        return instance;
    }
}
2.内部类模式的懒汉式单例
/**
 * 双重检查单例
 * 优点:性能高了,线程安全了,写法优雅,利用了java本身的语法特点,避免了内存浪费
 * 缺点:能够被反射破坏 可以通过在构造函数写判断来控制非法访问
 *
 */
public class LazyInnerClassSingleton {

    private LazyInnerClassSingleton() {
        if(LazyHolder.instance != null){
            throw new RuntimeException("不能非法访问");
        }
    }

    public static LazyInnerClassSingleton getInstance(){
        return LazyHolder.instance;
    }

    private static class LazyHolder{
        private static final LazyInnerClassSingleton instance = new LazyInnerClassSingleton();
    }
}
3.双重检查模式的懒汉式单例
/**
 * 双重检查单例
 * 优点:性能高了,线程安全了
 * 缺点:可读性难度加大,不够优雅
 *
 */
public class LazyDoubleCheckSingleton {
    private volatile static LazyDoubleCheckSingleton instance;

    public LazyDoubleCheckSingleton() {
    }

    public  static LazyDoubleCheckSingleton getInstance(){
        // 检查是否要阻塞
        if(null == instance){
            synchronized(LazyDoubleCheckSingleton.class){
                // 检查是否要创建实列
                if(null == instance) {
                    // 指令重排序问题 通过添加volatile关键字解决问题
                    instance = new LazyDoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}

3.注册式单例

1. 容器注册类似于spring ioc容器
public class ContainerSingleton {
    public ContainerSingleton() {
    }

    private static Map<String, Object> ioc = new ConcurrentHashMap<>();

    public static Object getInstance(String className){
        Object instance = null;
        if(!ioc.containsKey(className)){
            try {
                instance = Class.forName(className).newInstance();
                ioc.put(className, instance);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            return ioc.get(className);
        }
        return instance;
    }
}

// 测试类
public class ContainerSingletonTest {
    public static void main(String[] args) {
        Object instance1 = ContainerSingleton.getInstance("com.leo.singleton.register.ContainerSingleton");
        Object instance2 = ContainerSingleton.getInstance("com.leo.singleton.register.ContainerSingleton");
        System.out.println(instance1 == instance2);
    }
}
3. 枚举单例
/**
 * 优点:线程安全,优雅
 * 缺点:在某些情况下造成内存浪费。
 */
public enum EnumSingleton {
    INSTANCE;

    public Object data;

    public Object getData() {
        return data;
    }

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

    public static EnumSingleton getInstance(){
        return INSTANCE;
    }
}
4. ThreadLocal单例
public class ThreadLocalUser {

	public static ThreadLocal<TokenUser> userInfo = new ThreadLocal<TokenUser>();

	public ThreadLocalUser() {
	}

	public static TokenUser getUserInfo() {
		return (TokenUser) userInfo.get();
	}

	public static void setUserInfo(TokenUser user) {
		userInfo.set(user);
	}

}

三、单例能够通过反序列化破坏,但是可以通过重写readResolve 方法实现

/**
 * 单例能够通过反序列化破坏,但是可以通过重写readResolve 方法实现
 */
public class SerializableSingleton implements Serializable {

    public static final SerializableSingleton instance = new SerializableSingleton();

    public static SerializableSingleton getInstance(){
        return instance;
    }

    /**
     * 重写此方法可以防止被序列化破坏
     * @return
     */
    private Object readResolve(){
        return instance;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值