单例模式(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; }
-
声明周期托管(单例对象别人帮我们处理):这个有印象即可。
-
-