什么是单例
之前文章里面写过设计模式总结,里面有一类设计模式,叫创建模式,也就是说用来规范类对象的创建的,单例模式就是创建模式其中的一种。我们知道 Java 创建对象,通过 new 关键字来创建的话,new 一次就会新创建一个与之对应的对象,也就是在 JVM 堆中会分配内存空间给这个对象使用(Java 内存模型这块,可以参考周志明写的《深入理解 Java 虚拟机》)。如果 new 的对象过多,一是对象占用内存多,二是影响 GC 效率,严重的甚至会影响应用程序响应速度(跟 GC 有关)。如果说一个对象是无状态的,也就是说这个对象本身的属性,经过对象初始化过后,在以后各个线程中执行时候,是不会被修改的,那么这个对象就是无状态的,像这种无状态的对象,没有必要每次线程调用都去 new 一个对象,因为对象内部没有随业务变化的属性,因此是需要 new 一个这样的对象就行了,后期多线程访问就只需要访问这一个对象的属性即可。像这种情况,我们需要控制这个类的实例生成,保证整个 JVM 堆中只有 1 个此类的对象,这种设计模式就叫单例模式,单例意思就是单实例,英文叫 SingleTon。
常用的单例模式
这里虽然叫单例模式,但是实现的方式有很多种,看过网上的资料,可能叫法有很多,什么懒汉式、饿汉式,但是常用的我只做简单说明,也不取名,懂意思就行。
1、静态属性直接初始化对象,静态方法中直接返回此对象,适合简单对象的初始化,如下所示:
public class A{
private static final A instance=new A();
private A(){}
public static A instance(){
return instance;
}
}
2、复杂一点的对象,单例模式的初始化,一般采用双重校验方式,如下所示:
public class A {
private String field1;
private static A instance;
private A() {
}
public static A instance() {
if (instance == null) {
synchronized (A.class) {
if (instance == null) { //第二次校验,防止多线程操作导致对象覆盖
instance=new A();
instance.setField1("SingleTon"); //初始化对象属性
}
}
}
return instance;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
......
}
在整个开发过程中,可能使用第二种的情况会比较多,是需要记住的代码方式。
Spring
上面是通过手动写单例模式,不过 Spring 框架已经为我们提供了单例的容器,Spring 的 Bean 注入管理,默认就是单例的。当然可以通过修改 Scope 来修改单例或者是原型模式,这个可以百度一下具体了解。
我们在整个使用设计模式的过程中,一定要明白为什么要使用这种模式,而不是只记住它的代码是怎么写的。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于