1 单例模式的作用特点
保证一个类只有一个实例--即一个对象,
并且提供一个访问该实例的全局访问点--即类中有一个公共的方法--方法的返回该类的对象。
2 单利模式的常用场景
1.windows的任务管理器;--无论打开多少次都只能打开一个窗口
2.windows的回收站;
3.项目中的配置文件;
4.网站的计数器;
5.日志;
6.连接池;
7.Application;
8.spring的bean--默认是单例
9.servlet
10.springMVC和Struts2中,控制器对象
3 单例模式的优点
只生成一个实例--减少了系统的性能开销
4 单例模式的实现方式及优缺点
1.饿汉式--常用;线程安全、调用效率高、不能延时加载--缺点。
2.懒汉式--常用;线程安全、调用效率低、延时加载。
3.双重检测锁式--少用--线程安全、调用效率高、延时加载、偶尔出现问题--不建议使用。
4.静态内部类式--少用;线程安全、调用效率高、延时加载。(也是一种懒加载方式)。
5.枚举单例式--少用;线程安全、调用效率高、不能延时加载、实现简单--枚举本身就是单例模式。
4.1 饿汉式
4.1.1 代码:
package org.yxd.create;
/*
* 项目名称:DesignMode--设计模式学习
* 包名:org.yxd.create--创建型模式
* 类名:SingletonDemo1--单例模式之饿汉式
*/
public class SingletonDemo1 {
//类初始化时,立即加载这个对象--没有延时加载的优势。加载类时,天然的是线程安全。
private static SingletonDemo1 instance = new SingletonDemo1();
private SingletonDemo1(){}
//方法没有同步,调用效率高
public static SingletonDemo1 getInstance(){
return instance;
}
}
4.1.3 分析:
1.私有的、static的类对象
2.私有的构造器
3.一个共有的、static的方法--返回类的对象。
4.2 懒汉式
4.2.1 代码:
package org.yxd.create;
/*
* 项目名称:DesignMode--设计模式学习
* 包名:org.yxd.create--创建型模式
* 类名:SingletonDemo1--单例模式之懒汉模式
*/
public class SingletonDemo2 {
//类初始化时,不初始化这个对象--延时加载,真正用的时候再创建
private static SingletonDemo2 instance;
private SingletonDemo2(){}
//方法同步,调用效率低
public static SingletonDemo2 getInstance(){
if(instance==null){
instance=new SingletonDemo2();
}
return instance;
}
}
4.2.2 分析:
1.私有的、static的类对象--不new
2.私有的构造器
3.一个共有的、static的方法--返回类的对象。--同步
4.3 双重检测锁
4.3.1 源代码
package org.yxd.create;
/*
* 项目名称:DesignMode--设计模式学习
* 包名:org.yxd.create--创建型模式
* 类名:SingletonDemo3--单例模式之双重检测锁
*/
public class SingletonDemo3 {
//类初始化时,不初始化这个对象--延时加载,真正用的时候再创建
private static SingletonDemo3 instance = null;
private SingletonDemo3(){}
//方法同步在if中,调用效率高,但有时会出问题,不建议使用
public static SingletonDemo3 getInstance(){
if(instance==null){
SingletonDemo3 sc;
synchronized(SingletonDemo3.class){
sc=instance;
if(sc==null){
synchronized(SingletonDemo3.class){
if(sc==null){
sc=new SingletonDemo3();
}
}
instance=sc;
}
}
}
return instance;
}
}
4.3.2 分析
区别:
双重检测锁与懒汉式的差别--将同步移动到if中,同时if中有两sycnronized。
优势:安全、高效、延迟加载。
问题原因:
1.编译器优化
2.JVM底层内部模型
问题结果:
偶尔会出现问题。
4.4 静态内部类
4.4.1 源代码
package org.yxd.create;
/*
* 项目名称:DesignMode--设计模式学习
* 包名:org.yxd.create--创建型模式
* 类名:SingletonDemo4--单例模式之静态内部类
*/
public class SingletonDemo4 {
//内部类
private static class SingletonClassInstance{
private static final SingletonDemo4 instance=new SingletonDemo4();
}
//构造方法
private SingletonDemo4(){}
//调用该方法,加载静态内部类
public static SingletonDemo4 getInstance(){
return SingletonClassInstance.instance;
}
}
4.4.2 分析
区别:
1.没有static属性--使用了内部类的属性--不会立即加载
优势:安全、高效、延迟加载。
4.5 枚举
4.5.1 源代码
package org.yxd.create;
/*
* 项目名称:DesignMode--设计模式学习
* 包名:org.yxd.create--创建型模式
* 类名:SingletonDemo5--单例模式之枚举模式
*/
public enum SingletonDemo5 {
//定义一个枚举的元素,它就代表了一个Singleton的实例
INSTANCE;
//单例的操作
public void singletonOperation(){
System.out.println("枚举");
}
}
4.5.2 分析
区别:1.使用枚举--本身就是单例
优势:简单、安全、高效
问题:立即加载。
5 选用
占用占用少、不需要延时加载:
枚举 好于 饿汉式
占用资源多,需要延时加载:
静态内部类 好于 懒汉式