单例模式
单例模式在设计模式中,是较为容易理解的,所以就从单例模式开始了对于设计模式的学习。
单例模式的核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
常见应用场景:
1、Windows的Task Manager(任务管理器)就是一个很典型的单例模式,在任何情况下,只能打开一个任务管理器
2、Windows的Recycle Bin(回收站)也是很典型的单例应用,在整个系统的运行过程中,回收站一直维护着仅有的一个实例
3.项目中,读取文件配置的类,一般也只有一个对象,没有必要每次使用配置文件数据,都要new一个对象去读取
4、网站的计数器,一般也采用单例模式实现,否则难以同步
5、应用程序的日志应用,一般也是采用单例模式实现,这是因为共享的日志文件一直处于打开状态,只能有一个实例去操作,否则内容不好追加
6、数据库连接池的设计也是采用单例模式的设计,因为数据库连接是一种数据库资源
7、操作系统的文件系统,也是采用单例模式的实现,一个操作系统只能有一个文件系统
8、Application也是单例的典型应用
9、在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理
10、在servlet编程中,每个Servlet也是单例
11、在Spring MVC框架/Struts1框架中,控制器对象也是实例
单例模式的优点:
1、由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留在内存的方式来解决
2、单例模式可以在系统设置全局访问点,优化共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理
常见的五种单例模式:
1、饿汉式:线程安全,调用效率高,但是不能延时加载
2、懒汉式:线程安全,调用效率不高,但是能够延时加载
3、双重检测锁式:由于JVM底层内部模型原因,偶尔会出问题,不建议使用
4、静态内部类式:线程安全,调用效率高,能够延时加载
5、枚举单例:线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化的漏洞
饿汉式的实现:
/**
* @author ZLEI
* @Title
* @Description
* @date 2019-07-23 22:37
*
* 测试饿汉式单例模式
*
*/
public class SingletonDemo01 {
//天然的线程安全,不需要加synchronized,效率较高
//类初始化时,立即加载这个对象(即称为饿汉式的原因),没有延时加载的优势
private static SingletonDemo01 instance = new SingletonDemo01();
//私有化构造器
private SingletonDemo01()
{}
//方法没有同步,调用效率较高
public static SingletonDemo01 getInstance()
{
return instance;
}
}
懒汉式的实现:
/**
* @author ZLEI
* @Title
* @Description
* @date 2019-07-23 22:48
*
* 测试懒汉式设计模式
*
*/
public class SingletonDemo02 {
//类初始化时,不立即加载这个对象,延时加载,需要的时候再创建
private static SingletonDemo02 instance;
//私有化构造器
private SingletonDemo02()
{}
//方法同步,调用效率低
public static synchronized SingletonDemo02 getInstance()
{
if(instance == null)
instance = new SingletonDemo02();
return instance;
}
}
静态内部类式的实现:
import java.util.PrimitiveIterator;
/**
* @author ZLEI
* @Title
* @Description
* @date 2019-07-24 22:00
*
* 测试静态内部类式实现单例模式
* 这种方式线程安全,调用效率高,且延时加载
*
*/
public class SingletonDemo03 {
private static class SingletonClassInstance
{
private static final SingletonDemo03 instance = new SingletonDemo03();
}
public static SingletonDemo03 getInstance()
{
return SingletonClassInstance.instance;
}
private SingletonDemo03()
{}
}
枚举类式的实现:
/**
* @author ZLEI
* @Title
* @Description
* @date 2019-07-24 22:10
*
* 测试枚举式实现单例模式
*
*/
public enum SingletonDemo04 {
// 这个枚举元素本身就是一个单例对象
INSTANCE;
// 可以添加自己需要的操作
public void singletonOperation()
{}
}
如何选用:
1、单例对象 占用资源少 不需要延时加载:枚举式好于饿汉式
2、单例对象 占用资源多 需要延时加载:静态内部类式好于懒汉式