【单例模式】
可以保证一个类在内存中对象的唯一性。(例如配置对象)
要求:1 不允许其他地方用new创建该类的对象 2 在该类创建一个本类的实例 3 对外提供一个方法让其可以获取该对象。
步骤: 1 私有化构造函数 2通过new在本类中创建一个奔雷的对象 3定义一个共有方法,将创建的对象返回。
==================================================================================
【饿汉模式,懒汉模式 实现代码】
==================================================================================
【饿汉模式,懒汉模式 实现代码】
<span style="color:#000000;">package heima.yyx.demo01;
public class Demo003 {
public static void main(String[] args) {
Single1 s1 = Single1.getInstanse(); //验证饿汉模式是否满足单例要求
Single1 s2 = Single1.getInstanse();
System.out.println("s1对象和s2对象是否满足单例模式要求:"+(s1 == s2));
Single2 s3 = Single2.getInstanse();//验证懒汉模式是否满足单例要求
Single2 s4 = Single2.getInstanse();
System.out.println("s3对象和s4对象是否满足单例模式要求:" + (s3 == s4));
}
}
/**
* 饿汉式 , 在类加载的时候就创建一个对象
* @author yyx
*
*/
class Single1{
private static Single1 s = new Single1(); //在类中创建一个对象
private Single1(){ //构造函数私有化
System.out.println("执行饿汉模式的构造函数");
}
public static Single1 getInstanse(){ // 外界可以获取对象的公共接口, 用static保证可以类名调用
System.out.println("饿汉模式—获取唯一对象");
return s;
}
}
/**
* 懒汉模式,在对象第一次获取的时候进行对象的实例化
* @author yyx
*
*/
class Single2{
private static Single2 s = null; //在类中创建一个对象,先不进行实例化
private Single2(){ //构造函数私有化
System.out.println("执行懒汉模式的构造函数");
}
public static Single2 getInstanse(){ // 外界可以获取对象的公共接口, 用static保证可以类名调用,在第一次调用的时候实例化
if(s == null){
System.out.println("懒汉模式—实例化对象");
s = new Single2();
}
System.out.println("懒汉模式—获取唯一对象");
return s;
}
}
</span>
饿汉式和懒汉式区别
从名字上来说,饿汉和懒汉,
饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,
而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。
从线程安全上来讲, 饿汉模式是天生线程安全的因此没有线程安全的问题。而懒汉模式则不是线程安全的, 因为在懒汉模式中如果有多个线程同时对Single进行操作,那么在getInstance的时候容易发生线程混乱,导致类中的对象不一定唯一。
例如,当一个线程在判断s==null 为true后, 在还没有执行完new Single2();另一个线程也进入了if判断,此时另一个线程得到的也是s == null 为true, 但是此时第一个线程的new操作完成了, 类内对象已经不是null了, 但后来的线程韩式会创建一个,此时2次调用的getInstance所得到的对象就不是同一个对象。 因此可以做一些调整, 使用同步的方式略过这一点。
public static synchronized Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
此时的线程同步了, 也就不会发生上面的情况了。
但是却引出了下面的一个不同就是在耗时和资源上, 因为加了同步的方法耗时和资源消耗较大。而饿汉模式,类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。
总体来说, 两种单例模式都有很多能够修改的地方来弥补自身的不足, 具体的修改方式视实际情况而定。