单例模式
简单的介绍一下单列模式的两种情况:懒汉式及饿汉式。先从字面上来进行解析
单例模式是一个对象只会存在一个,而在这个基础上进行创建又大概可分为两种情况懒汉式及饿汉式,
懒汉式:当调用类的方法是对象才会被实例化,只会实例化一次。(从字面上理解,因为懒,所有自己不会进行实例化,只能等着人来调用之后在实例化)
饿汉式:当类创建之后此对象便被实例化。(从字面上理解,因为已经饥饿如狼,类被创建便会进行实例化)
下面用代码的形式来体现:
一个人拥有且只有一辆车来进行描述,不管调用车多少次,都只会是同一辆车。
懒汉式:
Car:类
package cn.test;
public class Car {
//代码体忽略不写
}
Person:类
package cn.test;
public class Person {
//单例模式,懒汉式
public static Car car;
public static Car getCar(){
if(car==null){
car=new Car();
}
return car;
}
}
Demo:类
package cn.test;
import org.junit.Test;
public class Demo {
@Test
public void run(){
System.out.println(Person.car);
Car car1 = Person.getCar();
System.out.println(car1);
Car car2 = Person.getCar();
System.out.println(car2);
System.out.println(Person.car);
}
}
这里我们发现第一次直接使用类名调用的时候便是一个null参数,没有使用方进行调用, 当调用一次getCar()方法后对象被创建且多次调用哈希地址都一样,这种编码格式便被称之为单例模式之懒汉式。
饿汉式:
Car:
package cn.test;
public class Car {
//代码体忽略不写
}
Person:
package cn.test2;
public class Person {
//单例模式,恶汉式
public static final Car car=new Car();
public static Car getCar(){
return car;
}
}
Demo:
package cn.test2;
import org.junit.Test;
public class Demo {
@Test
public void run(){
System.out.println(Person.car);
Car car1 = Person.getCar();
System.out.println(car1);
Car car2 = Person.getCar();
System.out.println(car2);
System.out.println(Person.car);
}
}
这里我们发现即使不需要调用方法,直接调用,对象便已经被创建了,这种编码格式称之为单例模式之饿汉式
这里还需要介绍两点是:饿汉式是线程安全的,它使用了static和final来进行了修饰
而懒汉式是非线程安全的,这里我们来模拟多线程的情况:
这里我们直接改写懒汉式的Demo代码
package cn.test;
import org.junit.Test;
public class Demo {
@Test
public void run() throws InterruptedException{
Thread t=new Thread(){
public void run() {
Car car=Person.getCar();
System.out.println(Thread.currentThread()+":"+car);
}
};
t.start();
Car car = Person.getCar();
System.out.println(Thread.currentThread()+":"+car);
}
}
这里我们发现了在多线程的环境中,懒汉式属于是线程不安全,这就需要我们对代码进行优化,既要满足懒汉式的编码规范,又要实现线程的安全,直接改写Person类:
package cn.test;
public class Person {
//单例模式,懒汉式,改造
private static final class abc{
private static final Car car=new Car();
}
public static Car getCar(){
return abc.car;
}
}
再次运行Demo类:
当我们再次测试的时候发现哈希值一样,这就表示了线程是安全,主要是通过static 和final来进行实现
对于static和final不牢靠的建议自行牢靠
通过前面的介绍,个人简单的概括一下,在编写代码时:
当多次访问只会产生一个对象时这种编码格式被普遍称之为单例模式,
而在进一步细化的时候
实例化对象是在成员位置被创建出来且使用了特定符修饰称之为饿汉式
通过方法的形式获取实例对象编码格式称之为懒汉式。