单例模式(singleton)

    xiaoxiao2023-10-09  154

    单例模式(singleton)

    引入(设计模式要明白为什么要这样写,而不是记代码,代码很少,但记不住)

    设计一个系统,比如叫做百度,开发搜索引擎。代码如下:

    class Baidu{ public void 搜索(String keyword){ } }

    执行搜索

    创建一个对象

    写完上述代码,还不能做事情,需要调用搜索方法,才能开始搜索。

    同一时间有很多很多人在使用系统,数量可达到上亿。如果每个人在搜索的时候,都创建一个对象,那么需要的空间非常大,即使集群也不一定能承受得了。但是,他们创建对象目的,只是为了调用搜索方法,进行搜索。那么,想个方案,只创建一个对象,让所有人都可用,在堆内存只开辟一个空间,每调用一次方法,临时执行一次,栈内存中执行,方法执行空间就回收了。

    由上一条,可知,单例模式有效减少内存占用。

    示例

    不要直接在src直接创建类,即使工程就一个类,也要创建包来存放。

    如下代码

    SingleTon single = new SingleTon();

    这种构造对象的方式,是通过代用无参构造方法实现的。每次用过new创建对象,是通过调用构造方法得到了,如果调不到构造方法,那就创建不了独享,所以把构造方法私有,就使用new创建不了了。

    1.让构造方法私有—保证外面不可以随便创建对象

    private SingleTon(){ }

    2.单例 不是无例—在本类中的某个成员位置上创建一个唯一对象

    构造方法:不行,私有 本身 调用不到

    块,如下方代码,在块中写,但是外面拿不到这个对象,必须要有返回值。创建了对象也无法给别人使用

    { SingleTon singleTon =new SingleTon() }

    方法,方法中可以写,但是每调用一个,创建一个,还是可以常见一个对象,保证不了唯一。

    public SingleTon xxx(){ SingleTon singleTon =new SingleTon(); }

    属性:如下,但是这样写,会导致栈内存溢出(StackOverflowError,注OutOfMemory是堆内存溢出),正常来说,套娃现象应该出现的是堆内存溢出的现象,不应该是栈内存溢出,原因是开辟空间的时候,调用了构造方法(内部可以调用私有),构造方法在栈内存执行,但是一个套一个执行,栈内存不断开辟新内存块,栈内存远小于堆内存,所以先耗尽。

    public SingleTon single =new SingleTon();

    改进上述方法

    public static SingleTon single =new SingleTon()

    这时就会在方法去创建唯一一份对象,static保证对象的唯一性。

    //外部类中调用 SingleTon s1 =SingleTon.single; SingleTon s2 =SingleTon.single; SingleTon s3 =SingleTon.single; //判断是不是一个对象 == System.out.println(s1 ==s2) //true System.out.println(s1.equals(s2)) //object类继承过来,默认比地址 true String中已经重写

    object中equals方法

    public boolean equals(Object obj){ return (this ==obj); }

    但是在外部类中

    SingleTon.single =null; 这样内部类的属性指向的静态区就被截断了,之后谁也用不了了,所以public不安全,所以需要对这个属性进行一定封装。 private static SingleTon single =new SingleTon()

    在提供一个外部获取对象的方法,方法名有个不成文的规定,get类名或者newInstance,但是这样创建会产生一个问题,使用获取对象方法之前必须要有对象,这样就拿不到对象,静态方法不需要对象,就可以调用。

    public SingleTon getSingleTon(){ return single;//引用类型 } public static SingleTon getSingleTon(){ return single;//引用类型 } //外部类中调用 SingleTon s1 =SingleTon.getSingleTon(); SingleTon s2 =SingleTon.getSingleTon(); SingleTon s3 =SingleTon.getSingleTon(); //判断是不是一个对象 == System.out.println(s1 ==s2) //true System.out.println(s1.equals(s2)) //object类继承过来,默认比地址 true String中已经重写

    以上是单例模式的设计思想。

    总结:

    私有方法的构造方法私有静态的当前类对象作为属性公有的静态的方法返回

    单例实现方式

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

    private static SingleTon single =new SingleTon() //立即加载 public static SingleTon getSingleTon(){ return single;//引用类型 }

    懒汉式(延迟加载):对象什么时候用到了,才会加载,坏处是由于没有操作好,导致异常,启动时候只有需要的加载,不需要的还没有创建,不会浪费空间。

    private static SingleTon single;//初始化只是一个属相,没有指向空间 public static SingleTon getSingleTon(){ if(single==null){ single =new SingleTon//第一次用到,什么时候用到才会创建。 } return single; }

    声明周期托管(单例对象别人帮我们处理):这个有印象即可。

    最新回复(0)