先看一个程序:
class Singleton { // 定义一个类
public void print() {
System.out.println("Hello World");
}
}
public class Test {
public static void main(String args[]) {
Singleton inst = null; // 声明对象
inst = new Singleton(); // 实例化对象
inst.print(); // 调用方法
}
}
上面的Singleton类里是存在构造方法的(如果一个类中没有明确的定义一个构造方法的话,会自动生成一个无参默认的构造方法),现在把构造方法修改一下:
class Singleton { // 定义一个类
private Singleton() {
} // 构造方法私有化
public void print() {
System.out.println("Hello World");
}
}
我们知道,构造方法被私有化,就无法在类外部实例化Singleton对象。
那么,此时,如何在Test类里面得到Singleton类的实例化对象并且调用print()方法?
首先,这个类的构造方法被私有化,只能被本类所调用,所以可以在本类中产生本类的实例化对象:
class Singleton { // 定义一个类
Singleton instance = new Singleton();//在本类中产生本类的实例化对象
private Singleton() {
} // 构造方法私有化
public void print() {
System.out.println("Hello World ");
}
}
我们知道,此时instance 属性只是一个普通属性,必须在类实例化对象后再可以使用,要想不需要实例化对象直接使用,可以使用static声明:
class Singleton { // 定义一个类
static Singleton instance = new Singleton();
private Singleton() {
} // 构造方法私有化
public void print() {
System.out.println("Hello World");
}
}
public class Test {
public static void main(String args[]) {
Singleton inst = null; // 声明对象
inst = Singleton.instance; // 实例化对象
inst.print(); // 调用方法
}
}
但是,我们知道,类中的全部属性都应该封装,以上的instance属性也应该封装:
private static Singleton instance = new Singleton();
而封装之后要想取得属性。要编写getter方法,不过这里的getter方法应该也由类名称直接调用,定义为static型,getInstance()方法:
class Singleton { // 定义一个类
private static Singleton instance = new Singleton();
private Singleton() {
} // 构造方法私有化
public void print() {
System.out.println("Hello World ");
}
public static Singleton getInstance() {
return instance;
}
}
public class Test {
public static void main(String args[]) {
Singleton inst = null; // 声明对象
inst = Singleton.getInstance(); // 实例化对象
inst.print(); // 调用方法
}
}
为什么这么做呢?此时程序之中的instance属性,属于static,那么,不管有多少个Singleton类的对象,都共同拥有同一个instance属性。
我们再来看,若getInstance()方法修改如下:
public static Singleton getInstance() {
instance = new Singleton();
return instance;
}
此时,发现,每调用一次getInstance()方法,就会实例化一个Singleton对象,这样的话,实例化对象就不是唯一的了,所以,这种情况不能让它出现,怎么办?可以在定义instance属性的时候增加一个final关键字:
private static final Singleton INSTANCE = new Singleton() ;
于是,最后的代码就变成了这样:
class Singleton { // 定义一个类
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
} // 构造方法私有化
public void print() {
System.out.println("Hello World .");
}
public static Singleton getInstance() {
return INSTANCE;
}
}
public class Test {
public static void main(String args[]) {
Singleton inst = null; // 声明对象
inst = Singleton.getInstance(); // 实例化对象
inst.print(); // 调用方法
}
}
这样的设计在设计模式上讲就称为单例设计模式(Singleton)。
单例设计模式的类型:
(1)饿汉式单例模式:当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断。上面的程序就属于饿汉式单例模式,
(2)懒汉式单例类:每次获取实例都会进行判断,看是否需要创建实例,如果一直没有人使用的话,那就不会创建实例。代码如下:
class Singleton { // 定义一个类
private static Singleton instance;
private Singleton() {
} // 构造方法私有化
public void print() {
System.out.println("Hello World .");
}
public static Singleton getInstance() {
if (instance == null) { // 没有实例化
instance = new Singleton(); // 实例化
}
return instance;
}
}
小结:单例模式的特点?
(1)构造方法被私有化(private);
(2)只能够通过getInstance()方法取得Singleton类的实例化对象,这样不管外部如何操作,最终也只有一个实例化对象;
(3)在单例设计模式之中,一定会存在一个static方法,用于取得本类的实例化对象。