Java创建型模式(一)——单例设计模式(饿汉式、懒汉式、枚举式,以及序列化反序列化破环单例模式和反射破环单例模式及破环单例模式的解决办法 | 完成详解,附有代码+案例)

文章目录

    • 单例设计模式
      • 4.1.1 单例模式的结构
      • 4.1.2 单例模式的实现
        • 4.1.2.1 饿汉式-静态变量方式
        • 4.1.2.2 饿汉式-静态代码块方式
        • 4.1.2.3 懒汉式-线程不安全
        • 4.1.2.4 懒汉式-线程安全
        • 4.1.2.5 懒汉式-双重检查锁
        • 4.1.2.6 饿汉式—枚举类
    • 4.3 单例模式存在的问题
      • 4.3.1序列化反序列化破环单例模式
      • 4.3.2 反射破环单例模式
    • 4.4 解决单例模式存在的问题
      • 4.4.1 序列化、反序列方式破坏单例模式的解决方法
      • 4.4.2 反射方式破解单例的解决方法

单例设计模式

提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

4.1.1 单例模式的结构

单例模式的主要有以下角色:

  • 单例类。只能创建一个实例的类,即只能创建一个对象。
  • 访问类(也就是测试类),使用单列类

4.1.2 单例模式的实现

单例设计模式分类两种:

​	饿汉式:类加载就会导致该单实例对象被创建	

​	懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建
4.1.2.1 饿汉式-静态变量方式

饿汉式,方式1----静态变量方式

该方式在成员位置声明Singleton类型的静态变量,并创建Singleton类的对象instance。instance对象是随着类的加载而创建的。如果该对象足够大的话,而一直没有使用就会造成内存的浪费。

//饿汉式,方式1----静态变量方式
public class SingLeton {
   

    // 1.私有构造方法,让外界不能创建该类的对象。
    private SingLeton() {
   }

    // 2.在本类中的成员位置创建本类的对象
    // 此处的static是根据3.中的方法是静态方法设置的
    private static SingLeton instance = new SingLeton();

    // 3.提供一个公共的访问方式,让外界获取该对象,所以用static
    public static SingLeton getInstance(){
   
        return instance ;
    }
}
===========================================================
  public class Test {
   
    public static void main(String[] args) {
   

        // 创建SingLeton类的对象
        SingLeton instance1 = SingLeton.getInstance();
        SingLeton instance2 = SingLeton.getInstance();

        // 判断获取的是否是同一个对象
        boolean b = instance1 == instance2;
        System.out.println(b);//true,说明创建了一个对象
    }
}
4.1.2.2 饿汉式-静态代码块方式

饿汉式,方式1----静态代码块方式

该方式在成员位置声明Singleton类型的静态变量,而对象的创建是在静态代码块中,也是对着类的加载而创建。所以和饿汉式的方式1基本上一样,当然该方式也存在内存浪费问题。

//饿汉式----静态代码块方式
public class SingLeton {
   

    // 1.私有构造方法,不让外界创捷该类的对象
    private SingLeton() {
   
    }

    // 2.声明SingLeton类型的变量
    private static SingLeton instace;//null

    // 3.静态代码块中进行赋值
    static {
   
        instace = new SingLeton();
    }

    // 4.对外提供获取该类对象的方法
    public static SingLeton getInstance(){
   
        return instace;
    }
}
=========================================================
  public class Test {
   
    public static void main(String[] args) {
   

        // 创建SingLeton类的对象
        SingLeton instance1 = SingLeton.getInstance();
        SingLeton instance2 = SingLeton.getInstance();

        // 判断获取的是否是同一个对象
        boolean b = instance1 == instance2;
        System.out.println(b);//true,说明创建了一个对象
    }
}
4.1.2.3 懒汉式-线程不安全

懒汉式----方式1----线程不安全

从代码我们可以看出该方式在成员位置声明Singleton类型的静态变量,并没有进行对象的赋值操作,那么什么时候赋值的呢?当调用getInstance()方法获取Singleton类的对象的时候才创建Singleton类的对象,这样就实现了懒加载的效果。但是,如果是多线程环境,会出现线程安全问题。

//懒汉式----方式1
public class Singleton {
   

    // 1.私有构造方法,不让外界创捷该类的对象
    private Singleton() {
   }

    // 2.声明Singleton类型的变量
    //只是声明没有赋值
    private static Singleton instance;

    // 3.对外提供访问方式
    public static Singleton getInstance() {
   
        //判断instace是否是null,
        //如果为null,说明还没有Singleton类的对象
        //如果没有,创建并返回;如果有,直接返回
        //如果没有if循环判断测试类的结果为false,
       // 因为每调用getInstance()方法就会创建新的Singleton对象
       //也违背单一规则
        if (instance == null){
   
            //假设两个线程,当线程1走到此行,cpu执行权被线程2抢走,
            //则线程2也会到判断里面,此时再执行会创建两个对象,
            //违背单一规则。
            instance = new Singleton();
        }
        return instance;
    }
}
=========================================================
  public 

你可能感兴趣的:(Java知识,java,设计模式,开发语言,intellij-idea,单例模式)