单例模式(Singleton)
    设计——>一个类只能创建一个对象 有效减少内存占用空间

    设计一个系统——>百度 搜索引擎
    public class Baidu{
    public void 搜索(){

    }
    }
    创建一个Baidu对象 new
    调用搜索方法 做事情 方法执行一遍
    同一时间会有很多人在使用这个系统
    对象——>只创建一个 堆内存种就只开辟一个空间
    调用一次方法——>临时执行一次 方法执行空间用完就回收

    单例模式的实现:
    1.私有的构造方法
    2.私有的静态的当前类对象作为属性
    3.公有的静态的方法返回当前类对象

    指的是对象的加载:
    饿汉式(立即加载) 对象启动时就加载
    好处 不会产生对象没有就拿来使用的问题 比如空指针异常
    不好处 启动项目加载对象过多 有些还没有使用 产生服务器压力过大

    懒汉式(延迟加载) 对象什么时候用 才会加载
    好处 启动项目时只有需要才加载 不需要的就不创建 不会浪费空间
    不好处 可能由于没有操作好 导致异常

    生命周期托管(单例对象别人帮我们处理) 对象加载过程交给别人

    饿汉式

    1. package singleton;
    2. public class SingleTon {
    3. //这个类只能创建一个对象
    4. //每一个类都有默认无参数的构造方法--->公有的
    5. //1.让构造方法变成私有的 让别人不能随便创建对象
    6. private SingleTon(){}
    7. //2.单例 不是无例 在本类中的某个成员位置上创建唯一的一个对象
    8. //构造方法 不行 因为构造方法本身就是构建的过程
    9. //程序块 不行 因为程序块没有返回值 无法把创建的对象给别人在使用
    10. //方法 不行 因为创建的对象不唯一 调用一次方法就会创建一次对象
    11. //因为其他三个成员创建的对象都不能满足需求 所以就只能在属性里创建对象
    12. private static SingleTon single = new SingleTon();
    13. //静态的属性上来就加载 都不用等对象创建 所以是饿汉式
    14. //通过私有的 修饰 来保证属性的安全 让别人不能随便访问
    15. //通过静态的 修饰 来保证对象只有一份 静态只加载一次
    16. //如果不加静态修饰 会出现错误 StackOverFlowError栈内存溢出错误
    17. //明明对象空间是在堆内存中 为什么会是栈内存溢出?
    18. //因为开辟空间时 调用了构造方法 构造方法执行是在栈内存中
    19. //3.提供一个获取单个对象的方法给用户
    20. //返回值 创建的对象
    21. //但是方法又需要对象来调用 要想不创建对象就调用方法
    22. //这就需要用静态来修饰这个方法
    23. //静态方法通过 类名.方法名 的方式就可以调用 无需创建对象
    24. public static SingleTon getSingleTon(){
    25. return single;//返回引用
    26. }
    27. }

    懒汉式

    1. package singleton;
    2. public class SingleTon {
    3. private SingleTon(){}
    4. private static SingleTon single;
    5. public static SingleTon getSingleTon(){
    6. if(single==null) {
    7. single = new SingleTon();//懒汉式(延迟加载) 对象什么时候要用 才会加载
    8. //返回对象的引用
    9. }
    10. return single;
    11. }
    12. }

    主方法

    1. package singleton;
    2. public class RunMain {
    3. public static void main(String[] args) {
    4. SingleTon s1 = SingleTon.getSingleTon();
    5. SingleTon s2 = SingleTon.getSingleTon();
    6. System.out.println(s1==s2);//true 比较地址
    7. System.out.println(s1.equals(s2));//true Object类继承过来的 默认比较地址
    8. }
    9. }