java基础与进阶程序员

设计模式之单例模式

2016-04-22  本文已影响100人  我的学长是王欣

什么是设计模式: 被反复使用,代码设计经验的总结

使用设计模式目的: 代码的重用,让代码更易于理解,保证代码可靠性

概念

适合场景

分类

步骤

  1. 构造器私有化
  2. 创建类的唯一实例,使用private static 修饰
  3. 提供一个获取实例的public方法
  4. enum枚举

饿汉式(线程安全)

class Singleton{
  //类加载时创建instance
  private static Singleton instance = new Singleton();

  private Singleton(){
  }

  public Singleton getInstance(){
    return instance;
  }

}

懒汉式

class Singleton{
  //仅仅声明instance
  private static Singleton instance ;

  private Singleton(){
  }

  public Singleton getInstance(){
    if(instance==null){
        instance = new Singleton();
    }
    return instance;
  }

}

上面这种getInstance有致命的缺陷,就是无法保证线程安全。而给整个方法加synchronized效率不高。考虑到同步操作只需要在第一次调用时才被需要,即第一次创建单例实例对象时。这就引出了双重检验锁

双重检验锁

是一种使用同步块加锁的方法。程序员称其为双重检查锁,因为会有两次检查 instance == null,一次是在同步块外,一次是在同步块内。为什么在同步块内还要再检验一次?因为可能会有多个线程一起进入同步块外的 if,如果在同步块内不进行二次检验的话就会生成多个实例了。

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

静态内部类

class Singleton{
  private static class SingletonHolder{//使用私有修饰符
    private static final Singleton instance = new Singleton();
  }
  private Singleton(){}

  public static final Singleton getInstance(){
    return SingletonHolder.instance;
  }
}

这种写法仍然使用JVM本身机制保证了线程安全问题;由于 SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖 JDK 版本。

枚举

enum Dog {
    DogA(1, "dog1"),DogB(2,"dog2");//实例

    int age;//私有变量
    String name;

    Dog(int age, String name) {//构造方法
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
//调用
public static void main(String[] args) {
      Dog dog = Dog.DogA;
      System.out.println(dog);

  }

总结

参考资料

我的博客

上一篇 下一篇

猜你喜欢

热点阅读