1、单例模式:
在当前系统中,某个类型的对象,最多只能有一个,就需要使用单例设计模式
2、单例模式的设计原则:
1、构造方法私有化
2、在类中创建好该类对象
3、在类中,给外界提供获取该对象的公有方式
2.1饿汉式
在加载类的同时,就要初始化静态成员变量,所以就同时将该类对象创建出来了
饿汉式:一有机会,马上就吃,不去等待。(一旦加载类型,马上创建对象)
//单例设计模式之饿汉式
//能多早创建对象就多早创建对象
public class Demo1_SingtonleHunger {
public static void main(String[] args) {
SingtonHunger sh1 = SingtonHunger.getInstance();
SingtonHunger sh2 = SingtonHunger.getInstance();
System.out.println(sh1==sh2);
}
}
class SingtonHunger{
//1.先私有构造方法
private SingtonHunger(){
}
//2.私有创建对象的方法
private static SingtonHunger sh = new SingtonHunger();
//3.通过创建对外界可见的方法来调用构造方法
public static SingtonHunger getInstance(){
return sh;
}
}
2.2懒汉式
在加载类的时候,不同时创建该类对象,等到需要获取这个对象时,才去创建这个对象
懒汉式:不着急、能不创建的时候,就不创建,能拖就拖
注意事项:
1、只有在sl == null的时候,才会创建对象
2、sl的判断和sl的赋值,不希望分离开,否则在多线程环境下,会出现多个对象的状态,所以sl的判断和sl的赋值,需要放到一个同步代码块中。
3、同步代码块的效率非常低,不是每次获取对象的时候,都需要判断锁对象,只有在sl为null的时候, 才应该判断锁对象,因此在外层需要嵌套一个if判断,判断sl是否为null
//单例模式之懒汉式
//能多晚创建对象就多晚创建对象
public class Demo2_SingletonLazy {
public static void main(String[] args) {
SingtonLazy sl1 = SingtonLazy.getInstance();
SingtonLazy sl2 = SingtonLazy.getInstance();
System.out.println(sl1==sl2);
}
}
class SingtonLazy {
// 1.私有构造方法
private SingtonLazy() {
}
// 2.私有创建对象的引用
private static SingtonLazy sl;
// 3.提供对外公开的方法创建对象
public static SingtonLazy getInstance() {
//最外层判断是否为空用来提高效率
if (sl == null) {
synchronized (SingtonLazy.class) {
//加上同步锁提高线程安全
if (sl == null) {
sl = new SingtonLazy();
}
}
}
return sl;
}
}
2.3老汉式
1、也是随着类的加载,而创建对象(也算是饿汉式的一种)
2、不再提供访问私有成员变量的方法
3、指向对象的引用设置为公有的访问权限,但是这样可能会被外界修改,因此在引用前面加上final,外界只能访问该变量,不能修改该变量的值
//单例设计模式之老汉式
//饿汉式的一种
class SingletonOlder{
//1.私有构造方法
private SingletonOlder(){
}
//2.加final创建对象外界,只能访问该变量,不能修改该变量的值
public static final SingletonOlder so = new SingletonOlder();
}
public class Demo3_SingletonOlder {
public static void main(String[] args) {
//3.调用实例
SingletonOlder so1 = SingletonOlder.so;
SingletonOlder so2 = SingletonOlder.so;
System.out.println(so1==so2);
}
}