单例模式
单例模式是什么?
保证系统中应用该模式的类只有一个实例,即该类只能创建一个对象。
饿汉单例模式
饿汉单例是什么?
在用类创建对象时,对象已经提前创建好
优点:适用于单例对象较少的情况
缺点:所有对象类加载的时候就实例化,如果有很多单例对象存在,初始化时就会导致大量的内存浪费
实现步骤
- 定义一个类,把构造器私有
- 定义静态变量储存对象
代码实现
类(通过HungryManModel访问该类的instance对象)
package hk;
/**
* 饿汉单例模式
*/
public class HungryManModel {
/**
* public 对方可以访问
* 对象只能是一个,所以用static静态成员变量
*/
public static HungryManModel instance=new HungryManModel();
/**
*私有化构造器,不是私有的化,可以创建多个对象
*一定要写出来并定义为private,因为有默认的
*/
private HungryManModel(){
}
}
Test类:
package hk;
public class Test {
public static void main(String[] args) {
//调用静态变量, 类名.变量名
HungryManModel h1=HungryManModel.instance;
HungryManModel h2=HungryManModel.instance;
System.out.println(h1);
System.out.println(h2);
}
}
输出结果:
由结果可知h1和h2为同一对象
懒汉单例模式
饿汉单例是什么?
在需要对象的时候才去创建对象
实现步骤
- 定义类,私有化构造器
- 定义一个静态变量存储一个对象
- 提供返回对象的方法
代码实现
类
package hk;
public class LazyMode {
/*
2. 不能new,否则就变成了饿汉模式
最好别定义为public,对方如果第一次调用为LazyMode h2=LazyMode.instance; 就会变为null
*/
private static LazyMode instance;
//1.
private LazyMode(){}
//提供方法,对外返回一个单例对象
public static LazyMode getInstance(){
/*
3. 不能直接这样写,否则每调一次这个方法,就会产生一个新对象
instance=new LazyMode();
return instance;
*/
if (instance == null){
instance=new LazyMode();
}
return instance;
}
}
Test类:
package hk;
public class Test {
public static void main(String[] args) {
LazyMode h1=LazyMode.getInstance();
LazyMode h2=LazyMode.getInstance();
System.out.println(h1);
System.out.println(h2);
}
}
输出结果:
由结果可知h1和h2为同一对象
懒汉单例线程安全问题
懒汉单例模式是线程不安全,当调用方法时,首先要经过if判断,在多线程场景下,就可能存在多个线程同时进入if判断,此时对象还未创建,那么就会多个线程都去创建对象,这样单例模式就被破坏了。
解决方案
具体可查看这篇文章
懒汉单例模式解决线程安全问题
总结
从内存角度看,懒汉模式要比饿汉好一些,当调用这个类的其它功能,不需要这个对象时,懒汉模式就不必提前创建对象,节省内存。饿汉模式即使不需要对象,但此时也会创建对象(与类一起加载)。