3.5、构造方法私有化(重点)
在讲解本操作之前,首先来观察如下的程序。
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类对象的时候,程序出现了编译错误,因为构造方法被私有化了,无法在外部调用,即:无法在外部实例化Singleton类的对象。
那么现在就需要思考:在保证Singleton类之中的构造方法不修改不增加,以及print()方法不修改的情况下,如何操作,才可以让类的外部通过实例化对象再去调用print()方法?
思考过程一:使用private访问权限定义的操作只能被本类所访问,外部无法调用,那么现在既然构造方法被私有化了,就证明,这个类的构造方法只能被本类所调用,即:现在在本类之中产生本类实例化对象。
class Singleton { // 定义一个类 Singleton instance = new Singleton() ; private Singleton() {} // 构造方法私有化 public void print() { System.out.println("Hello World .") ; } } |
思考过程二:对于一个类之中的普通属性,默认情况下一定要在本类存在了实例化对象之后才可以进行调用,可是现在在Singleton类的外部无法产生实例化对象,那么必须想一个办法,让Singleton类中的instance属性可以在没有Singleton类实例化对象的时候来进行调用,可以使用static完成,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属性应该进行封装,而封装之后要想取得属性要编写getter方法,只不过这个时候的getter方法应该也由类名称直接调用,定义为static型。
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属性,那么既然是有同一个,那么又有什么意义呢?
现在做一个简单的思考:如果说现在一个类只希望有唯一的一个实例化对象出现,应该控制构造方法,如果构造方法对外部不可见了,那么现在肯定无法执行对象的实例化操作,必须将构造方法隐藏,使用private隐藏。
既然清楚了这个目的,不过本程序依然有一个问题。
public static Singleton getInstance() { instance = new Singleton() ; return instance ; } |
本操作语法没有错误,也不需要考虑是否有意义,但是现在的代码是允许这样做的,而这样做发现之前表示唯一一个实例化对象的所有努力就白费了,那么必须想办法废除掉这种做法,可以在定义instance的时候增加一个final关键字。
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)。
面试题:请编写一个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() ; // 调用方法 } } |
特点:构造方法被私有化,只能够通过getInstance()方法取得Singleton类的实例化对象,这样不管外部如何操作,最终也只有一个实例化对象,在单例设计模式之中,一定会存在一个static方法,用于取得本类的实例化对象。
对于单例设计模式,在日后的开发之中,只会用到此概念,但是具体的代码很少去编写。
扩展(可以不会):
对于单例设计模式按照设计模式的角度而言,分为两种:
· 饿汉式:之前写的程序就属于饿汉式,因为在类之中的INSNTACE属性是在定义属性的时候直接实例化;
· 懒汉式:在第一次使用一个类实例化对象的时候才去实例化。
范例:观察懒汉式
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 ; } } |
这些概念清楚就行了,对于单例设计再次强调:记清楚代码的结构以及操作的特点,以后这种代码虽然不会由你自己去写,但是概念一定会用到。