- 单例设计模式
1,定义:什么是单例设计模式?
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
2,好处:在java语言中,单例带来了两大好处:
1.对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级的对象而言,是非常可观的一笔系统开销。
2.由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间。
所以对于系统的关键组件和被频繁操作的对象,使用单例模式便可以有效地改善系统性能。
单例的参与者非常简单,只有单例类和使用者两个;
例的实现主要是通过以下两个步骤:
1,将该类的构造方法定义为私有方法,这样其他处的代码就无法通过调用该类的构造方法来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例;
2,在该类内提供一个静态方法,当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用。
应用场景举例:
- 1.需要生成唯一序列的环境
- 2.需要频繁实例化然后销毁的对象。
- 3.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
- 4.方便资源相互通信的环境
在我们的windows桌面上,我们打开了一个回收站,当我们试图再次打开一个新的回收站时,Windows系统并不会为你弹出一个新的回收站窗口。,也就是说在整个系统运行的过程中,系统只维护一个回收站的实例。这就是一个典型的单例模式运用。
继续说回收站,我们在实际使用中并不存在需要同时打开两个回收站窗口的必要性。假如我每次创建回收站时都需要消耗大量的资源,而每个回收站之间资源是共享的,那么在没有必要多次重复创建该实例的情况下,创建了多个实例,这样做就会给系统造成不必要的负担,造成资源浪费。
再举一个例子,网站的计数器,一般也是采用单例模式实现,如果你存在多个计数器,每一个用户的访问都刷新计数器的值,这样的话你的实计数的值是难以同步的。但是如果采用单例模式实现就不会存在这样的问题,而且还可以避免线程安全问题。同样多线程的线程池的设计一般也是采用单例模式,这是由于线程池需要方便对池中的线程进行控制
同样,对于一些应用程序的日志应用,或者web开发中读取配置文件都适合使用单例模式,如HttpApplication 就是单例的典型应用。
- 实现方式(5种):
3.1:饿汉方式
public class HungrySingleton {
//私有成员变量,不管有没有用到先new创建出来
private static HungrySingleton hungrySingleton = new HungrySingleton();
//私有构造方法
private HungrySingleton() {}
//提供公共方法给外界访问
public static HungrySingleton getHungrySingleton() {
return hungrySingleton;
}
}
3.2:懒汉方式(延迟加载,需要用的时候在创建)
public class LazySingleton {
//私有成员
private static LazySingleton lazySingleton = null;
//私有构造方法
private LazySingleton(){}
//提供公共方法给外界访问
public static LazySingleton getLazySingleton() {
if(lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
}
}
3.3:实现三:线程安全的“懒汉模式”
class LazySingleton {
//私有成员
private static LazySingleton lazySingleton = null;
//私有构造方法
private LazySingleton(){}
//提供公共方法给外界访问,加synchronized关键字实现同步
public static synchronized LazySingleton getLazySingleton() {
if(lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
优点:在多线程情形下,保证了“懒汉模式”的线程安全。
缺点:众所周知在多线程情形下,synchronized方法通常效率低,显然这不是最佳的实现方案。
3.4:DCL双检查锁机制(DCL:double checked locking)
public class LazySingleton {
//私有成员
private static LazySingleton lazySingleton = null;
//私有构造方法
private LazySingleton(){}
//提供公共方法给外界访问,加synchronized关键字实现同步
public static synchronized LazySingleton getLazySingleton() {
if(lazySingleton == null) {
synchronized (LazySingleton.class) {
if(lazySingleton == null) {
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
}
优点:内存占用率高,效率高,线程安全,多线程操作原子性。
3.5:枚举实现:
//枚举单例
public class SingleEnum {
/*
* 1.从Java1.5开始支持;
* 2.无偿提供序列化机制;
* 3.绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候;
* */
private static SingleEnum INSTANCE;
private String others;
SingleEnum() {
}
}