创建型模式 -单例模式

单例模式

介绍: 单例模式,是采取一定方法在,整个系统中,对某个类只能存在一个对象实例,并只提供一个获取其对象的实例


饿汉式(静态常量)

//饿汉式(静态常量)
class Test {
    // 1.构造器私有化
    private Test() {

    }
    //2.使用组合方式,构建此类的实例
    private final static Test test = new Test();

    //3.公共接口提供方法创建

    public static Test getInstance() {
        return test;
    }

}

优点:简单,在类加载时候就完成了实例化,解决了线程之间的同步问题

缺点:在类加载的时候就完成了实例化(有可能不是调用了getInstance方法),不能确定没有其他方式导致加载,造成了内存浪费


饿汉式(静态代码块)

final关键字用法

//饿汉式(静态代码块)
class Test1 {
    // 1.构造器私有化
    private Test1() {

    }
    //2.不加final(否则一开始就要赋值,或者在静态代码块,构造函数(只适用于非静态常量)初始化,),注意这里加不加final都是可以的

    private  static Test1 test1;
   //构建此类的实例(在静态代码块)
    static{
        test1 = new Test1();
    }

    //3.公共接口提供方法创建

    public static Test1 getInstance() {
        return test1;
    }

}

优缺点同上(只不过是变量初始化的方式不同)


懒汉式(线程不安全)

**懒汉式与饿汉式不同在:饿汉式是类加载直接构建的惟一的对象,而懒汉式是在调用其对外暴露的方法时才进行构建实例
注意:线程不安全是在if判断时发生的,当线程一与线程二同时判断出test3为空时,将会创建两个对象
**

//懒汉式(线程不安全)
class Test3{
    //表示此对象
    private static Test3 test3;
    //私有化构造对象
    private Test3(){

    }
    //提供公共方法构造
    public static Test3 getInstance(){
        if(test3 == null){
            test3 = new Test3();
        }
        return test3;
    }
}

优点:起到了懒加载效果(什么时候用到什么时候加载)
缺点:只能在单线程下使用

** 不推荐**


懒汉式(线程安全)

//懒汉式(线程安全)
class Test4{
    //表示此对象
    private static Test4 test4;
    //私有化构造对象
    private Test4(){

    }
    //加入静态同步代码块将改类加锁,在调用该方法前,需要获得内置锁
     //再多线程下保证其可见性
    // (释放锁的时候会刷新主内存,其他线程在获取锁的时候会强制从主内存中读取,)和原子性
    public static synchronized Test4 getInstance(){
        if(test4 == null){
            test4 = new Test4();
        }
        return test4;
    }
}

优点:解决了线程不安全问题
缺点:效率太低了,每次要获取实例时都要进行同步,其实只执行一次即可

** 不推荐**


懒汉式(双重检索模式)

注意:volatile主要是保证了test5新建对象的有序性,在新建对象时分为三步 1.创建实例分配内存 2.调用构造方法,为属性赋值,初始化 3.将其引用给变量
该作用主要是预防第一个if判断 直接执行了3步骤(给变量赋值引用)而未执行初始化

//懒汉式(双重检索模式dcl)
class Test5{
  //唯一实例,保证有序性,可见性
  private  volatile static Test5 test5;
  //私有化构造方法
  private Test5(){}
  //提供方法
  public static Test5 getInstance(){
  //使用voliatille 防止直接执行3步骤,而没有执行2步骤
      if(test5 == null){
          //锁住其类对象,在调用代码块时需要获取锁
          synchronized (Test5.class){
              if(test5==null){
                  test5=new Test5();
              }
          }

      }
      return  test5;
  }
}

** 该方法完美解绝了问题**


静态内部类

原理:在主类加载时,内部类并不会加载因此可以通过调用方法创建内部类(类在加载的时候,就保证了线程安全)


//静态内部类实现
class Test6{
    private  Test6(){

    }
    //通过内部类来加载外类实例
    private static class singleTest6{
        private static Test6 TEST6 =new Test6();
    }
  //只有在调用此方法时,该内部类才会被加载
    public  Test6 getInstance(){
       return singleTest6.TEST6;
    }
}

优点:通过内部类加载机制实现了懒加载,并且根据类在加载的时候是安全的解决了多线程问题
推荐使用


枚举

在枚举中实例只会被创建一次

//枚举实现
enum Test7{
    INSTANCE;
}

优点:解决了懒加载,及线程安全和序列化安全问题
推荐使用

主要推荐使用的模式

饿汉式,懒汉式(双重检索模式),枚举方式,静态内部类


单例模式注意事项及细节

  • 单例模式保证了系统内存中只存在一个对象,对于一些需要频繁创建销毁的对象,使用该模式可以提高系统性能。

  • 实例化单例对象的时候,要使用相应获取对象的方法,而不是使用new

  • 单例模式使用的场景:需要频繁创建和销毁的对象,创建对象时耗时过多(重量级对象)。但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(数据库,session工厂)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值