设计模式(1) - 创建型模式 - 单例模式

1. 单例模式的介绍

单例设计模式,就是采取一定方法保证在整个软件系统中对某只能存在一个对象实例  

2. 用途

确保任何情况下都绝对只有一个实例。

3. 优点

1. 内存里面只有一个实例,减少了开销
2. 避免资源的多占和重用

4. 编码coding

4.1 饿汉式

  • 优点
    1. 写法比较简单
    2. 避免了多线程会出现的问题
  • 缺点
    如果从始至终都没有用过这实例,则必然会导致内存的浪费。
  • 结论
    还不错,可以用的。哈哈

4.1.1 代码方案1

/**
 * 单例设计模式(饿汉式)
 * @author immortal
 *
 */
public class SingleObject {
    
    

	//1. 构造方法私有化,防止外部new对象
	private SingleObject() {
    
    };
	
	//2. 当类初始化的时候就创建了对象。
	private static final SingleObject instance = new SingleObject();
	
	//3. 提供一个外部接口,获取对象。
	public static SingleObject getInstance() {
    
    
		return instance;
	}
}

4.1.1 代码方案2

/**
 * 单例模式-饿汉式
 * @author immortal
 *
 */
public class SingleObject02 {
    
    

	// 1. 构造方法私有化
	private SingleObject02() {
    
    };
	
	// 2. 声明变量
	private static SingleObject02 instance = null;
	
	// 3. 初始化
	static {
    
    
		instance = new SingleObject02();
	}
	
	// 4. 定义方法返回
	public static SingleObject02 getInstance() {
    
    
		return instance;
	}
	
}

4.2 懒汉式

  • 优点
    起到了懒加载的效果,不会造成内存的浪费

4.2.1 方案1–线程不安全(一般别用)

我也就是写一写,反正一般情况下也是不要用的。

在这里插入图片描述

4.2.2 方案2-解决多线程(效率不行)

在这里插入图片描述

4.2.3 方案3-双重检查

这个方案不错, 也容易理解

/**
 * 单例模式-双重检查
 * @author immortal
 *
 */
public class SingleObj {
    
    

	//1. 构造方法私有化,防止外面new
	private SingleObj() {
    
    };
	
	//2. 定义变量 注意:volatile 关键字
	private static volatile SingleObj instance;
	
	//3. 方法
	public static SingleObj getInstance() {
    
    
		
		if (instance == null) {
    
    
			// * 比如这里有n个线程 都进来了。
			// * 然后这里是同步代码块,只有一个线程进去了,创建了对象
			// * 然后创建了对象。对象由 volatile 修饰,会立马更新到其他线程,
			// * 然后其他的线程(除这n个以外的)再来,连第一个 if(上面的if) 都进不了了
			// * 然后现在只存在 第一批进入 第一个if 的n-1个线程。
			// * 其他的n-1个线程依次进入。然后一看有了,就会全部退出。齐活。
			// * 最后这个同步代码块,就不会在执行了。大大的提高了效率。
			synchronized (SingleObj.class) {
    
    
				if (instance == null) {
    
    
					instance = new SingleObj();
				}
			}
		}
		
		return instance;
	}
}

4.3 java静态内部类的方式

不错,可以使用

4.3.1 代码实现

public class SingleObj {
    
    

	// 1. 构造方法私有化
	private SingleObj() {
    
    };
	
	// 2. 声明 静态 内部类
	private static class SingleObjInstance {
    
    
		private static final SingleObj INSTANCE = new SingleObj();
	}
	
	// 3. 方法
	public static SingleObj getInstance() {
    
    
		return SingleObjInstance.INSTANCE;
	}
}

4.3.2 原因

1. 此方法可以实现懒加载,因为 外部类加载时并不需要立即加载内部类
2. 当第一次调用getInstance的时候,在第一次加载了类。此时才实例化了这个类。实现了懒加载
3. jvm 帮助我们保证了线程的安全性,在类进行初始化的时候,别的线程是无法进入的。所以也避免了多线程的问题。

4.4 枚举的方式(**)

4.4.1 代码实现

public enum SingleObj {
    
    

	INSTANCE;
	
	/**
	 * 干活啦,干活的方法之一。。。。。
	 */
	public void ganHuoLa() {
    
    
		System.out.println("这个是我干活的方法之一。。。");
	}
	
	/**
	 * 如果写了这个,你获得对象的话,可以这么写: SingleObj.getInstance();
	 * 个人感觉,好处的话,就是看起来跟其他的单例模式看起来获取对象的方式差不多
	 * 如果不写这个方法。想获取对象的话。SingleObj.INSTANCE 就可以
	 * 这方法我感觉没啥用。写不写都行。
	 * 写了的话,只是看起来比较好看而已
	 */
	public static SingleObj getInstance() {
    
    
		return INSTANCE;
	}
	
}

4.4.2 优点

既可以避免多线程同步的问题,而且还能防止反序列化创建对象 
可以避免反射来创建对象。
也是Java 集合框架创办人,Joshua Bloch所推荐的一种方式。

他也是懒汉式的。可以通过反编译看出来。

平常也很少用枚举类型。建议大伙们,可以先大概了解一下枚举
如果创建单例对象的时候,需要参数,建议使用setter 和 getter 方法进行设置

猜你喜欢

转载自blog.csdn.net/weixin_42041788/article/details/105584892
今日推荐