单件模式的应用实例诸如线程池、缓存,对话框、数据库连接类、一些硬件的驱动程序的对象等。如果在这些问题中实例化好多的对象就会造成一些资源被随意的使用造成管理的混乱,单件模式就可以很好的解决此类问题。
顾名思义单件模式就是在程序中只实例化一个对象,那么怎么样才能保证我们的程序在运行过程中只会实例化一个对象呢?我们都知道在Java中创建一个对象用new操作符即可完成,一般的情况下,我们都会把类的构造函数用public修饰符(其他的关键字以后还会提到)修饰,这就导致了程序在后来的使用过程中,我们允许在其他的地方随意的创建对象。有一个特殊的修饰符private(写数据库操作的程序时常用到)它所修饰的方法只允许在该类中被使用,这是我们可以封住构造函数不允许被随意的创建:
class Sinleton {
private Singleton() {
//代码
......
}
//代码
........
}
问题之一可以解决了,但是产生了新的问题,在该类以外我们无法调用该类的构造函数去创建一个对象,我们都知道
在一些javavbean的开发过程中,经常会写一些get...()和set...()之类的方法,我们这样做的目的在于不想客户随意更改的一些参数或者是不想用户知道我们是怎么样处理数据的,只是对外提供可以按照我们的要求更改数据——封装。这时我们可以采取这个方法把实例化一个对象放到一个方法中作为方法的返回值,但是我们还要考虑,如果只是仅仅的在未返回时的话,还是不能保证的,解决方法一:
class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getsingleton() { // 1
if(singleton == null) //2
singleton = new Singleton(); //3
return singletonl; //4
}
//代码
.........
}
首先解释一下为什么getsingleton()方法要用static修饰符?在Java中方法用static修饰符咋可以利用类名.方法名的方式直接的调用该方法;其次是我们再累中直接声明了一个Singleton的类型的成员,并用static却保其唯一性,并在getsingleton()中利用一些语句保证了该成员只会被实例一次。
在该类的外面我们已经可以得到Singleton类的对象了,是不是在这时我们就可以应用了呢?不是!在Java中我们都知道,Java是一个可以支持多线程的语言,由于多线程的原因,在程序执行过程中即getsingleton()方法时,如果有两个线程同时都在执行这个方法,并且是交叉执行的,结果会造成实例化了两个对象:
thread1.1
thread2.1
thread1.2
thread2.2
thread1.3
thread2.3
thread1.4
thread2.4
最终是两个对象!
对于这个问题我们有两种解决的办法:办法一:在getsingleton()前面加上synchronized关键字;方法二:
是在声明类成员singleton是就对其初始化,getsingleton(){return singleton;}即可。
注意两种方法各有利弊,方法一在程序中加入synchronized关键字会是程序的执行效率大大降低;方法二占用了额外的内存,在程序执行时就为我们初始化了对象,这时就会在堆中生申请内存空间存放该对象,如果我们不用这个对象一直被放在呢里就是浪费。不过在不要求性能的情况下我们可以采用方法一,内存空间充足时可用方法二。