1.单例模式
定义:一个类只允许产生一个实例化对象。
我们先想想类的实例化对象是如何产生的?
它是通过类的构造方法产生的。现在只让一个类产生一个实例化对象,我们就要考虑从它的构造方法入手,我们可以把构造函数私有化,这样它就不能在类的外部被调用了。
但如果我们还想在类的外部调用类内函数,就必须通过类的实例化对象来调用,但构造函数已经被私有化了,我们就需要在类内部产生一个实例化对象。
我们先来看一个简单的例子:
class Person{
//在类内部可以访问私有构造,所以在类内部可以产生实例化对象
Person per = new Person();
private Person(){//private声明构造方法
}
public void print(){
System.out.println("hello person");
}
}
如果我们想在主类中调用Person类中的print()函数,就必须通过Person类的实例化对象来定义,但per只是Person类中的一个普通属性,所有的普通属性必须在有实例化对象的时候才能进行内存空间的分配,但构造函数被私有化了,在类的外部是无法进行对象实例化的。所以我们必须想办法,让per这个属性在没有实例化对象的时候就可以使用,我们就想到了static这个关键字,static是类属性,可以通过类名调用,与对象实例化对象无关。
class Person{
//在类内部可以访问私有构造,所以在类内部可以产生实例化对象
static Person per = new Person();
private Person(){//private声明构造方法
}
public void print(){
System.out.println("hello person");
}
}
public class Test{
public static void main(String[] args){
Person person = null;// 声明对象
person = Person.per;
person.print();
}
}
上边这个代码虽然可以取得Person类的实例化对象,但对类中的属性应该私有化,用private修饰,如果想要取得private封装的属性,就得用getter()方法,此时要访问的是static修饰的属性,所以提供的getter()方法也必须是static修饰的。
class Person{
//在类内部可以访问私有构造,所以在类内部可以产生实例化对象
private static Person per = new Person();
private Person(){//private声明构造方法
}
public static Person getPer(){
return per;
}
public void print(){
System.out.println("hello person");
}
}
public class Test{
public static void main(String[] args){
Person person = null;// 声明对象
person = Person.getPer();
person.print();
}
}
上边这段代码就是一个完整的单例模式
单例模式的两种形式
单例模式又分为懒汉式单例和饿汉式单例。
- 饿汉式单例:上来就new
这个上来就new的意思是,不管你是否使用Person这个类的对象,只要该类加载了,就一定会创建一个公共的per对象。我们希望在整体的操作中只能够有一个实例化对象,所以一般会在前边加上final关键字。
class Person{
//在类内部可以访问私有构造,所以在类内部可以产生实例化对象
private final static Person per = new Person();
private Person(){//private声明构造方法
}
public static Person getPer(){
return per;
}
public void print(){
System.out.println("hello person");
}
}
public class Test{
public static void main(String[] args){
Person person = null;// 声明对象
person = Person.getPer();
person.print();
}
}
- 懒汉式单例模式:当第一次去使用Person类的实例化对象的时候才会去new,为其此时实例化对象。
class Person{
//在类内部可以访问私有构造,所以在类内部可以产生实例化对象
private static Person per;
private Person(){//private声明构造方法
}
public static Person getPer(){
if(per == null){// 表示此时还没有实例化
per = new Person();
}
return per;
}
public void print(){
System.out.println("hello person");
}
}
public class Test{
public static void main(String[] args){
Person person = null;// 声明对象
person = Person.getPer();
person.print();
}
}
懒汉式单例模式会存在线程安全问题,而饿汉式单例模式不会。
所以一般推荐使用饿汉式单例模式。