阿里云【名师课堂】Java面向对象开发87 ~ 88:单例设计模式
@
复习:《阿里云【名师课堂】Java面向对象开发71 ~ 72:接口的设计模式》。
87:单例设计模式
单例设计是指一个类只允许产生一个实例化对象,下面观察一个简单程序。
class Singleton {
public void print() {
System.out.println("Hello World!") ;
}
}
public class TestSingleton {
public static void main(String args[]) {
Singleton s = null ; // 声明对象
s = new Singleton() ; // 实例化对象
s.print() ; // 调用方法
}
}
以上的程序在进行对象实例化的时候调用了Singleton
类的无参构造方法(因为没有定义任何构造,就会自动生成一个无参的、什么都不做的默认构造)。
但是如果现在在Singleton
类中明确定义一个私有的无参构造:
观察类中定义有私有构造时
class Singleton {
private Singleton() {};
public void print() {
System.out.println("Hello World!") ;
}
}
这时既然类中明确提供了无参构造,就不会有默认无参的构造,也就是说此时在进行对象实例化时会调用自己定义的私有的无参构造,这显然会有问题:
既然构造方法被私有化了,就表示无法外部无法调用该构造,也就是外部不能产生新的实例化对象了。那么也就证明,此时的类是一个相对而言封闭的状态。
如果还想要继续调用Singleton类中的print()这个普通方法,就必须要有实例化对象。在构造私有化的情况下我们怎么实例化一个对象呢?
- 考虑在类的内部产生一个实例化对象。
1、产生实例化对象
class Singleton {
private Singleton() {};
Singleton instance = new Singleton() ; // 内部产生实例化对象,类的内部允许访问私有方法
public void print() {
System.out.println("Hello World!") ;
}
}
2、使用static关键字实例化对象
现在Singleton类内部的instance对象(属性)是一个普通属性,所有的普通属性必须在有实例化对象的时候才能够进行内存空间的分配,而现在外部无法产生实例化对象,所以就必须想一个办法,可以在Singleton类中没有实例化对象产生的时候也可以使用instance。
- 《阿里云【名师课堂】Java面向对象开发44 ~ 47:static关键字》
- static的核心:共享
class Singleton {
private Singleton() {};
static Singleton instance = new Singleton() ; // 内部产生实例化对象
public void print() {
System.out.println("Hello World!") ;
}
}
public class TestSingleton {
public static void main(String args[]) {
Singleton s = null ; // 声明对象
s = Singleton.instance ; // static定义的属性可以通过类名.属性访问
s.print() ; // 调用方法
}
}
2、使用static关键字定义方法
以上虽然取得了Singleton类的实例化对象,但是一般情况下对于类中的属性应该使用private进行封装,比如这里的static Singleton instance = new Singleton() ;
。
如果要想取得封装的属性,就必须提供有getter方法,不过此时访问的是一个封装
并且static
的属性,并且这个类无法在外部进行实例化对象的创建,所以应该再提供有一个static的方法,因为static方法也不受实例化对象的控制。
class Singleton {
private Singleton() {};
private static Singleton instance = new Singleton() ; // 内部产生实例化对象
public static Singleton getInstance() {
return instance ;
}
public void print() {
System.out.println("Hello World!") ;
}
}
public class TestSingleton {
public static void main(String args[]) {
Singleton s = null ; // 声明对象
s = Singleton.getInstance() ; // static定义的属性/方法可以通过类名.属性/方法访问
s.print() ; // 调用方法
}
}
费这么大功夫,目的是什么呢?为什么非要把构造私有化?
- 只希望类中产生一个唯一的实例化对象。
对于单例设计模式,有两种形式:
- 懒汉式
- 饿汉式
上述程序就是饿汉式的实际应用。简单地说,不管是否真正使用Singleton类的对象,只要该类加载了,那么一定会创建好一个公共的instance对象。并且操作中只能有一个实例化对象,所以一般还会对其追加上final。
范例:饿汉式单例设计(修改上述程序)
······
private final static Singleton INSTANCE = new Singleton() ;
public static Singleton getInstance() {
return INSTANCE ;
}
······
特点:
- 构造方法私有化,外部无法创建新的实例化对象,只能通过static方法取得实例化对象。
范例:懒汉式单例设计(修改上述程序)
指的是当第一次使用Singleton类对象的时候才会为其进行实例化操作。
······
private static Singleton instance ;
public static Singleton getInstance() {
if (instance == null) { // 当判断到还没有实例化时,进行实例化操作
instance = new Singleton() ;
}
return instance ;
}
······
88:多例设计模式(理解)
用生活中事物来举例多例设计模式:
- 要求描述一周天数的类,只能有七个对象;
- 要求描述生物学性别,只能有两个对象。
- ······
class Sex {
public static final int MALE_FLAG = 1 ;
public static final int FEMALE_FLAG = 0 ;
private static final Sex MALE = new Sex("男") ;
private static final Sex FEMALE = new Sex("女") ;
private String title ;
private Sex(String title) {
this.title = title ;
};
public static Sex getInstance(int flag) {
switch(flag) {
case MALE_FLAG:
return MALE ;
case FEMALE_FLAG:
return FEMALE ;
default:
return null ;
}
}
public String toString() {
return this.title ;
}
}
public class TestSingleton {
public static void main(String args[]) {
Sex a = Sex.getInstance(Sex.MALE_FLAG) ;
System.out.println(a) ;
}
}
总结
不管多例还是单例设计模式,特点都是:
- 构造方法私有化;
- 类内部一定提供有一个static方法用于取得类的实例化对象。
- 单例和多例设计模式实际使用并不多,但是必须清楚代码结构,尤其是单例设计,会在面试用到。多利设计模式先理解概念,目前多例已经被枚举所取代了。