1. 定义
单例其实就是唯一实例的意思,也就是说一个类只有唯一的一个实例。
保证一个类仅有一个实例,并提供一个访问它的全局访问点
2. 使用范围
1. 应用中某个实例对象需要频繁的被访问。
2. 应用中每次启动只会存在一个实例。
在程序开发中,我们在日志 数据库连接使用时会经常使用单例模式。因为我们在频繁的使用该类进行日志打印或者数据库操作,同时又不希望产生过多的对象,此时我们就需要使用到单例模式。不仅这两种案例,在java的Runtime类,也是一个典型的单例模式使用案例。
3. 实现原理
单例模式的实现方式:定义一个该类的静态变量,然后再定义一个获取到该静态变量的静态方法。示意图如下:
需要注意的是,在单例模式中需要把构造函数设置位private,防止外部通过构造方法获取该类的实例。
单例模式有二种展示方式:
1.饿汉式
public class Singletion{
private static Singletion instance = new Singletion();
private Singletion(){
//..
}
public static Singletion getInstance(){
return instance;
}
}
2.懒汉式
public class Singletion{
private static Singletion instance = null;
private Singletion(){
//..
}
public static Singletion getInstance(){
if(instance == null){
instance = new Singletion();
}
return instance;
}
}
这两种的区别就在于实例创建的时机,一种是在该类加载的时候创建,另一种是在需要获取时创建。
但是有一点需要注意的是,懒汉式在单线程中运行是没有问题的,而在多线程中就会出现严重的问题,那就是当多个线程都在进行if(instance == null)的判断时,就会产生多个实例。这就违背了单例模式的原则。所以为了解决这个问题我们需要添加synchronized(同步)机制,同时避免在大量调用获取该类实例的场景下低效的问题,我们需要添加一个双检测锁机制代码如下:
public class Singletion{
private static Singletion instance = null;
private Singletion(){
//..
}
public static Singletion getInstance(){
if(instance ==null){
synchronized(Singletion.class) {
if(instance == null){
instance = new Singletion();
}
}
}
return instance;
}
}
最后,总结一句,通常情况下推荐使用饿汉式单例模式,这时最简单也是最安全的的做法
4. 优缺点
优点:
1、提供了对唯一实例的受控访问。
2.由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
3.允许可变数目的实例。
缺点:
1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
2.单例类的职责过重,在一定程度上违背了“单一职责原则”。
3.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。