GoF 定义:确保一个类只有一个实例,并提供一种全局访问的方法。( Ensure a class only has one instance, and provide a global point of access to it.)
通俗说法:有些类从业务上看,只需要初始化一次,且从头到位就只需要使用一个实例。例如,专一的绅士对天发誓,一生一世只爱她一个人。如果不小心重新new了另一个实例,那麻烦就大了。单例模式从代码层面避免这样的错误,把new新对象的车门彻底焊死!
举一个例子,下面的代码中,MyLover类描述了一个【现实中真的对象】,使用单体模式实现,获得实例的唯一接口是调用getLover(),它会给你返回一个安排得明明白白的lover对象。除此之外,无论怎么瞎搞,你都无法获得第二个身份证号码不一样的对象。
不信来看代码。
import java.util.Random;
public class Main {
public static void main(String[] args) {
// 只能使用getLover() 方法获得对象
MyLover lover = MyLover.getLover();
System.out.println("lover's id: " + lover.getIdentityNum());
// 尝试创建一个叫做lover1的实例,但实际是与lover是同一个引用!
MyLover lover1 = MyLover.getLover();
System.out.println("lover1's id: " + lover1.getIdentityNum());
// 若使用以下语句new一个对象,编译阶段就会报错,因为无法访问到构造方法。
// MyLover tryToNewALover = new MyLover();
}
}
// MyLover类,以Singleton模式实现
class MyLover {
/* 存储MyLover的对象
使用private限制外部访问,禁止更改
既然只需要一个lover,不如用static设置为类的属性
*/
private static MyLover darlingLover = new MyLover();
// lover的基本信息
private long identityNum;
private String name;
private int age;
/* 这是类的构造方法
设为private,使得外部无法访问
把new一个对象的可能性彻底毁灭
*/
private MyLover() {
Random ran = new Random();
this.identityNum = ran.nextLong();
}
// MyLover类只能通过这个接口获得一个实例
public static MyLover getLover(){
return darlingLover;
}
public long getIdentityNum(){
return identityNum;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
第7行和第11行尝试获得两个对象,但实际是这两者指向同一个引用,打印出来的ID是一样的↓
好了,单例的事情说清楚了,突然发现心真累。。。