Java设计模式

设计模式-Java-建造型01-单例模式

2022-06-27  本文已影响0人  茂茂的小破号

1 定义

单例模式确保一个类仅有一个实例,并且自行初始化且向整个系统提供使用。

2 使用场景

3 优缺点

优点:

  1. 保证内存里只有一个实例,减少内存开销。
  2. 避免资源被多重占用。
  3. 设置全局访问点,优化共享资源的访问。
    缺点:
  4. 违背开闭原则:单例模式通常没有接口很难扩展,一般只有修改原有的类。
  5. 违背单一职责原则:单例模式的功能通常都写在一个类中
  6. 测试困难:在并行开发环境中,如果单例模式没有完成,是不能进行测试的,没有接口也不能使用mock的方式虚拟一个对象。

4 实现

饿汉式

饿汉式表明在类被加载的时候就建立单例对象。

public class HungrySingleton {
    private static final HungrySingleton hungrySingleton = new HungrySingleton();

    private HungrySingleton(){};

    public static HungrySingleton getHungrySingleton(){
        return hungrySingleton;
    }
}

懒汉式

只有在第一次获取单例对象时采取创建单例对象,优点:节省内存开销,加快程序启动速度。

实现方式1-synchronized

public class LazySingleton {
    private static volatile LazySingleton lazySingleton;

    private LazySingleton(){}

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

其中synchronized与volatile关键字是为了保证线程安全,缺点是每次访问都需要加锁,并发性差,并且消耗更多资源。

实现方式2-双重检查

实现方式1是在方法上加锁,每次get的时候都会执行加锁动作,即使实例已经被初始化完成。那么能否在判断实例未初始化时再加锁进行创建呢,这样get实例的时候就不用加锁了。实现方式如下:

public class LazySingletonDoubleCheck {
    private static volatile LazySingletonDoubleCheck instance;

    private LazySingletonDoubleCheck(){};

    public LazySingletonDoubleCheck getInstance(){
        if(instance == null){
            synchronized(LazySingletonDoubleCheck.class){
                if(instance == null){
                    instance = new LazySingletonDoubleCheck();
                }
            }
        }
        return instance;
    }
}

其中第一次检查是看实例是否被初始化,没有的话则对类进行加锁,获得锁后会再次判断实例是否被初始化(防止多个线程同时加锁的情况),如果实例未被初始化,则进行初始化。

上一篇 下一篇

猜你喜欢

热点阅读