1.关系类图
2.单例介绍
定义:指一个类只有一个实例,且能自行创建这个实例的一种模式.例如,windows中只能打开一个任务管理器,这样可以避免因打开多个任务管理器而造成内存资源浪费,而出现各个窗口显示内容的不一致错误.
单例模式特点:
1)单例只有一个实例对象
2)该单例对象必须由单例类自行创建
3)单例类对外提供一个访问单例的全局点
单例的优点:
1)单例例模式1可以保证内存中只有一个实例,减少了内存的消耗.
2)可以避免对资源的多重占用
3)单例模式设置全局访问点,可以优化和共享资源的访问
单例的缺点:
1)单例模式一般没有借口,扩展困难,如果要扩展,则修改了原来的代码,没有第二种途径违背开闭原则
2)在并发测试中,单例模式不利于代码调试.在调试过程中,如果单例中代码还没有执行完,也不能模拟生成一个新的对象.
3)单例模式通常写在一个类中,如果功能设计不合理,和容易违背单一职责原则
单例的应用场景:
1)需要频繁创建一些类,使用单例模式可以降低系统的内存压力,减少gc
2)某类只要求生成一个对象的时候,比如一个班的班长,每个人的身份证号
3)某类创建实例需要消耗资源过多,或者实例化消耗较长,且经常使用
4)频繁访问数据库或者文件的对象
5)默写类需要频繁实例化,而创建的对象又频繁销毁的时候,不如多线程的线程池,网络的连接池
6)对于一些控制硬件级别的操作,或者从协同上讲是单一控制的操作,如果有多个实例,则系统会乱套
7)当对象需要被共享的场合.由于单例模式只允许创建一个对象,共享对象可以节省内存,并加快对象访问速度.比如web中的配置对象,数据库连接池
3.代码实现
3.1饿汉式(线程安全)
//饿汉式(静态变量)
class Singleton {
//1. 构造器私有化, 外部能new
private Singleton() {
}
//2.本类内部创建对象实例
private final static Singleton instance = new Singleton();
//3. 提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
return instance;
}
}
3.2懒汉式(线程非安全)
//饿汉式(静态变量)
class Singleton {
//1. 构造器私有化, 外部能new
private Singleton() {
}
//2.本类内部创建对象实例
private static Singleton instance;
static { // 在静态代码块中,创建单例对象
instance = new Singleton();
}
//3. 提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
return instance;
}
}
3.3懒汉式(线程安全)
// 懒汉式(线程安全,同步方法)
class Singleton {
private static volatile Singleton instance;
private Singleton() {}
//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
//同时保证了效率, 推荐使用
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
3.4静态内部类(线程安全)
// 静态内部类完成, 推荐使用
class Singleton {
private static volatile Singleton instance;
//构造器私有化
private Singleton() {}
//写一个静态内部类,该类中有一个静态属性 Singleton
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
public static synchronized Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
3.5枚举(线程安全,枚举会编译成静态内部类)
//使用枚举,可以实现单例, 推荐
enum Singleton {
INSTANCE; //属性
public void sayOK() {
System.out.println("ok~");
}
}
线程安全,枚举会编译成静态内部类)
//使用枚举,可以实现单例, 推荐
enum Singleton {
INSTANCE; //属性
public void sayOK() {
System.out.println("ok~");
}
}