继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用!
4. 创建者模式
4.1 特点
- 使用者不需要知道对象的创建细节
4.2 单例模式
4.2.1使用场景
- 单例类:且仅能创建一个实例类
- 访问类:使用单例类
4.2.2 创建方式
4.2.2.1 饿汉式
- 类加载时就会创建单例对象
- 存在内存浪费问题
- 静态成员变量
public class SingletonDemo1 {  
    //私有构造函数  
    private SingletonDemo1(){}  
    //类中创建对象  
    private static SingletonDemo1 instance = new SingletonDemo1();  
    //提供访问方式,让外界获取  
    public static SingletonDemo1 getInstance(){  
        return instance;  
    }  
}
测试代码,结果为true
//    获取对象  
    SingletonDemo1 singletonDemo1 =SingletonDemo1.getInstance();  
    SingletonDemo1 singletonDemo2 =SingletonDemo1.getInstance();  
//    判断是否一样  
    System.out.println(singletonDemo1 == singletonDemo2);  
}
- 静态代码块,测试类似,结果依旧为true
public class SingletonDemo2 {  
    //私有构造函数  
    private SingletonDemo2(){}  
    //类中创建对象  
    private static SingletonDemo2 instance ;  
//    静态代码块赋值对象  
    static {  
        instance = new SingletonDemo2();  
}  
    //提供访问方式,让外界获取  
    public static SingletonDemo2 getInstance(){  
        return instance;  
    }  
}
4.2.2.2 懒汉式
- 使用对象时才创建对象
- 线程不安全方式,测试代码类似,单线程结果为true,多线程为false
public class SingletonDemo3 {  
        //私有构造函数  
        private SingletonDemo3(){}  
        //类中创建对象  
        private static SingletonDemo3 instance ;  
    public static SingletonDemo3 getInstance(){  
//        若instance为null,则未创建,创建新对象,否则返回instance  
        if(instance == null)  
            instance = new SingletonDemo3();  
        return instance;  
    }
}
- 线程安全式,代码仅仅一点改动,测试代码类似,单线程多线程均为true,但执行效率低
	//和之前一样
    public static synchronized SingletonDemo3 getInstance(){  
//        若instance为null,则未创建,创建新对象,否则返回instance  
        if(instance == null)  
            instance = new SingletonDemo3();  
        return instance;  
    }
- 双重检查锁式,解决效率低下问题,但在多线程下可能会空指针,原因是JVM在实例化对象中会进行优化和指令重排序
	//和之前一样
    public static SingletonDemo4 getInstance(){  
//        若第一次判断instance不为null,不需要抢占锁,直接返回instance  
        if(instance == null)  
        {  
            synchronized (SingletonDemo4.class)  
            {  
//                第二次判断  
                if(instance == null)  
                    instance = new SingletonDemo4();  
            }  
        }  
        return instance;  
    }
改进则是加volatile,比较推荐使用,如图![![[Pasted image 20221227214947.png]]](https://img-blog.csdnimg.cn/4da53f072f7b4396b5813bf1ca482fb7.png)
- 静态内部类,JVM加载外部类时不加载静态内部类,只有内部类属性/方法被调用时才会被加载并初始化静态属性结果为true
public class SingletonDemo5 {  
    //私有构造函数  
    private SingletonDemo5(){}  
    //类中创建对象  
    private static class Singleton{  
        private static final  SingletonDemo5 INSTANCE = new SingletonDemo5();  
    }  
    //提供访问方式,让外界获取  
    public static SingletonDemo5 getInstance(){  
        return Singleton.INSTANCE;  
    }  
}
4.2.2.3 枚举式(恶汉式)
4.2.2.3.1 特点
线程安全,只会装载一次,书写简单,唯一一种不会被破坏掉的方式
4.2.2.3.2 代码
public enum SingletonDemo6 {  
    INSTANCE;  
}
测试类似,结果为true
4.2.3 存在问题
4.2.3.1 问题
会破坏单例模式唯一性
4.2.3.2 序列化及反序列化
- 源代码
public class SingletonDemo7 implements Serializable {  
    //私有构造函数  
    private SingletonDemo7(){}  
    //类中创建对象  
    private static SingletonDemo7 instance = new SingletonDemo7();  
    //提供访问方式,让外界获取  
    public static SingletonDemo7 getInstance(){  
        return instance;  
    }  
}
- 测试代码,结果两者显示不一样,不是唯一对象,破坏单例模式
public static void readObject() throws Exception  
{  
    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("./a.txt"));  
    SingletonDemo7 singletonDemo1 = (SingletonDemo7) objectInputStream.readObject();  
    System.out.println(singletonDemo1);  
    objectInputStream.close();  
}  
public static void writeObject() throws Exception  
{  
    ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./a.txt"));  
    outputStream.writeObject(SingletonDemo7.getInstance());  
    outputStream.close();  
}
public static void main(String[] args) throws Exception {
//    writeObject();  
    readObject();  
    readObject();  
}
4.2.3.3 反射
- 源代码使用懒汉式静态成员变量代码
- 测试代码
public static void main(String[] args) throws Exception {
//    获取Singleton的字节码对象  
    Class clas = SingletonDemo1.class;  
//    获取无参构造函数对象  
    Constructor declaredConstructors = clas.getDeclaredConstructor();  
//    取消访问检查  
    declaredConstructors.setAccessible(true);  
//    创建singleton对象  
    SingletonDemo1 o = (SingletonDemo1) declaredConstructors.newInstance();  
    SingletonDemo1 o1 = (SingletonDemo1) declaredConstructors.newInstance();  
    System.out.println(o == o1);  
}
4.2.3.4 解决办法
4.2.3.4.1 序列化与反序列化
- 在Singleton类中添加readsolve()方法
- 如图![![[Pasted image 20221228210925.png]]](https://img-blog.csdnimg.cn/153a6a13c90f435d853a440063b1354d.png) 
4.2.3.4.2 反射
- 加boolean 判断
- 如图![![[Pasted image 20221228211702.png]]](https://img-blog.csdnimg.cn/537a413b13e34a6190ac80bc0fd2de0f.png) 
4.2.4 Runtime
4.2.4.1 特点
- 使用单例模式来进行对象创建
- 具体是饿汉式的静态成员变量,如图
 ![![[Pasted image 20221228213348.png]]](https://img-blog.csdnimg.cn/efbc4d6a7511416bb34d8585ac6414e2.png) 
4.2.4.2 简单使用
- 测试代码
public static void main(String[] args) throws Exception {
//    获取对象  
    Runtime runtime = Runtime.getRuntime();  
//    执行控制台命令 ipconfig    Process process = runtime.exec("ipconfig");  
//    获取文件输入流  
    InputStream inputStream = process.getInputStream();  
//    创建字节数组接收  
    byte[] bytes = new byte[1024*1024*100];  
//    获取最终长度  
    int read = inputStream.read(bytes);  
//    将字节数组转换为字符串  
    System.out.println(new String(bytes,0,read,"GBK"));  
}
- 结果![如图![[Pasted image 20221228214017.png]]](https://img-blog.csdnimg.cn/8c2f02703072470eafae8b9199b2ff2a.png) 












![Isaac Sim 机器人仿真器介绍、安装与 Docker [1]](https://img-blog.csdnimg.cn/3ccf549e4387408f89b7b08d5acfb609.png)





