如果说Spring框架是乾坤大挪移,那么设计模式就是九阳神功,学会了九阳神功在学其他的武功就会非常容易,设计模式是解决复用性功能的一套经验方法,我们写代码的时候最忌讳写死,应该考虑复用性、扩展性,我们今天来说说设计模式中的单例模式,这也是最简单的一种模式,简单归简单,很多框架中都使用了单例模式,所以这个模式也非常重要。
单例模式
定义:单例模式属于创建型的设计模式,通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)。
优点:单例只有一个实例,这样做节约系统资源、全局唯一。
缺点:因为单例是类,不是接口,所以扩展性差些。
适用场景:
1.windows系统中的资源管理器、回收站。
2.系统中的订单号生成单例类,笔者公司曾经使用单例双检索这种方式。
3.Spring框架中的bean一般都是默认单例,所有bean的请求都会返回这个唯一的实例。
4.mybais框架中的ErrorContext是用在每个线程范围内的单例,用于记录该线程的执行环境错误信息。
实现方式:
1.饿汉式:在类加载时就已经创建,无法延时加载,如果一直没有使用,可能会造成内存浪费,但是线程安全,调用效率高。
public class SingleTon {
//方式1:饿汉式
//类静态成员,类加载过程中创建,线程安全
private static SingleTon singleTon = new SingleTon();
private SingleTon(){}
public static SingleTon getSingleTon(){
return singleTon;
}
}
2.懒汉式:使用时再实例化对象。//方式2:懒汉式
//每次获取都需要检查,使用时加载,多线程访问会存在线程安全问题
private static SingleTon singleTon = null;
private SingleTon(){}
public static SingleTon getSingleTon(){
if(null==singleTon){
singleTon = new SingleTon();
}
return singleTon;
}
//synchronized效率较低
public static synchronized SingleTon getSingleTon(){
if(null==singleTon){
singleTon = new SingleTon();
}
return singleTon;
}
3.双重检索//方式3:双重检索
//两次判断+volatile(防止指令重排序)+synchronized(多线程锁)
private static volatile SingleTon singleTon = null;
private SingleTon(){}
public static SingleTon getSingleTon(){
if(null==singleTon){
synchronized (SingleTon.class){
if(null==singleTon){
singleTon = new SingleTon();
}
}
}
return singleTon;
}
4.内部类//方式4:内部类
//内部类在外部类调用的时候才加载,延迟加载,线程安全。
public class SingleTon {
//方式4:内部类
//内部类在外部类调用的时候才加载,延迟加载,线程安全。
public static class Holder{
public static SingleTon singleTon = new SingleTon();
}
public static SingleTon getSingleTon(){
return Holder.singleTon;
}
}
5.枚举方式public enum SingleTon {
//方式5:枚举类
//类加载时进行加载,一直没有使用,可能造成浪费
INSTANCE;
public static SingleTon getSingleTon(){
return INSTANCE;
}
}