单例模式
所谓的单例设计指的是一个类只允许产生一个实例化对象。
单例模式有很多好处,它能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间;能够避免由于操作多个实例导致的逻辑错误。如果一个对象有可能贯穿整个应用程序,而且起到了全局统一管理控制的作用,那么单例模式也许是一个值得考虑的选择。
范例:使用private声明构造方法
class Singleton{
private Singleton() { // private声明构造
}
public void print() {
System.out.println("Hello World");
}
}
这个时候类中已经明确的提供了一个私有的构造方法,那么默认生成的无参构造不再产生,此时进行对象实例化的时候一定会有错误。
一旦构造方法被私有化了,表示外部无法调用构造即外部不能够产生新的实例化对象。此时的类是一个相对而言封闭的状态。
如果此时还想继续调用Singleton类的print()方法,那么必须提供实例化对象。考虑到封装的特点,可以在类的内部产生一个实例化对象。
范例:在类的内部产生实例化对象
class Singleton{
// 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
Singleton instance = new Singleton() ;
private Singleton() { // private声明构造
}
public void print() {
System.out.println("Hello World");
}
}
现在Singleton内部的instance对象(属性)是一个普通属性,所有的普通属性必须在有实例化对象的时候才能进行内存空间的分配,而现在外部无法产生实例化对象,所以必须想一个办法,可以在Singleton没有实例化对象产生的时候,也可以将instance进行使用。此时,联想到使用static关键字。
范例:使用static产生实例化对象
class Singleton{
// 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
static Singleton instance = new Singleton() ;
private Singleton() { // private声明构造
}
public void print() {
System.out.println("Hello World");
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton = null ; // 声明对象
singleton = Singleton.instance ;
singleton.print();
}
}
以上虽然可以取得Singleton类的实例化对象,但是对于类中属性应该使用private进行封装,要想取得private属性,应该提供getter()方法。由于此时访问的是static属性,并且这个类无法在外部提供实例化对象,因此应该提供一个static的getter()方法,因为static方法也不受对象实例化控制。
范例:static的getter()方法
class Singleton{
// 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
private static Singleton instance = new Singleton() ;
private Singleton() { // private声明构造
}
public static Singleton getInstance() {
return instance ;
}
public void print() {
System.out.println("Hello World");
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton = null ; // 声明对象
singleton = Singleton.getInstance() ;
singleton.print();
}
}
对于单例设计模式也有两类形式:懒汉式、饿汉式。
上面的代码实际上就是饿汉式的应用。不管你是否使用Singleton类的对象,只要该类加载了,那么一定会自动创建好一个公共的instance对象。既然是饿汉式,就希望整体的操作之中只能够有一个实例化对象,所以一般还会在前面追加一个final关键字
范例:饿汉式单例模式
class Singleton{
// 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象
private final static Singleton INSTANCE = new Singleton() ;
private Singleton() { // private声明构造
}
public static Singleton getInstance() {
return INSTANCE ;
}
public void print() {
System.out.println("Hello World");
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton = null ; // 声明对象
singleton = Singleton.getInstance() ;
singleton.print();
}
}
范例:懒汉式单例模式
特点:当第一次去使用Singleton对象的时候才会为其产生实例化对象的操作.
class Singleton{
private static Singleton instance ;
private Singleton() { // private声明构造
}
public static Singleton getInstance() {
if (instance==null) { // 表示此时还没有实例化
instance = new Singleton() ;
}
return instance ;
}
public void print() {
System.out.println("Hello World");
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton = null ; // 声明对象
singleton = Singleton.getInstance() ;
singleton.print();
}
}
饿汉式单例上来就new,懒汉式单例用时再new。
写就写饿汉式单例,懒汉式单例存在线程安全问题(双重加锁单例模式)