java学习笔记-设计模式之单例模式五种实现方式

一、简介

单例模式的核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

常见案例:回收站

优点:

1、单例模式只生成一个实例,降低系统性能开销。

2、方便资源共享

常见单例模式:

饿汉式:线程安全、效率高、不能延迟加载,当全程没使用到该实例时,浪费系统资源。

懒汉式:线程安全(加锁)、调用效率相对饿汉式低,可以延迟加载。:

双重检测锁式:由于jvm内部底层模型原因,偶尔会出现问题,不建议使用

静态内部类式:线程安全,调用效率高,可以延迟加载

枚举单例:线程安全,调用效率高,不能延迟加载

二、简单实现

1、饿汉式单例模式简单实现

核心:

1、利用static关键字声进行类的实例化。

2、私有化构造器

3、提供一个public方法获取类的实例

代码如下:

package com.zwh.gof23;
/**
 * 单例模式(饿汉式)
 * 1、构造器私有化
 * 2、类初始化时立即加载。
 * 特点:
 * 1、线程安全
 * 2、调用效率高
 * 3、不能延时加载
 * @author zwh
 *
 */
public class SingletonPatternStarving {
	//类初始化时就加载这个对象(static关键字),此时不涉及多个线程对象访问该对象的问题,
	//虚拟机保证只会加载一次该类,肯定不会发生并发访问的问题。
	//但是如果只是加载本类,而不是要调用geiInstance(),甚至永远没有使用,则造成资源浪费
	private static SingletonPatternStarving instanse=new SingletonPatternStarving();
	
	//构造器私有化
	private SingletonPatternStarving(){
	}
	
	public static SingletonPatternStarving getInstance(){
		return instanse;
	}
}

 

2、懒汉式单例模式简单实现

核心步骤与饿汉式一致,只是在声明实例变量时不进行初始化,在调用全局方法时进行初始化,代码如下:

package com.zwh.gof23;
/**
 * 懒汉式到单例模式
 * @author zwh
 * 特点:
 * 1、延迟加载,在调用到getInstance方法时才加载。资源利用率高
 * 2、调用getInstance方法时需要同步,并发效率较低
 */
public class SingletonPatternSlacker {
	//实例不初始化,需要时再进行初始化
	private static SingletonPatternSlacker instance;
	
	//私有化构造器
	private SingletonPatternSlacker(){}
	
	/**
	 * 初始化类的实例,并保证在调用本方法时才会创建实例,保证线程安全。
	 * @return
	 */
	public static synchronized SingletonPatternSlacker getInstance(){
		if(null == instance){
			instance = new SingletonPatternSlacker();
		}
		return instance;
	}
}

 

 

3、双重检测锁单例模式

由于jvm内部底层模型原因,偶尔会出现问题,不建议使用。核心在于将锁放到if条件中。只有第一次初始化实例时需要进行同步。代码如下:

package com.zwh.gof23;

/**
 * 双重检测锁单例模式 将同步内容放到if条件内,只有第一次创建实例时需要进行同步,提高效率
 * 
 * @author zwh
 * 
 */
public class SingletonPatternDoubleCheckLock {

	// 声明变量
	private static SingletonPatternDoubleCheckLock instance;

	/**
	 * 全局访问方法,获取类的实例
	 * 
	 * @return
	 */
	public static SingletonPatternDoubleCheckLock getInstance() {
		if (null == instance) {
			SingletonPatternDoubleCheckLock sc;
			synchronized (SingletonPatternDoubleCheckLock.class) {
				sc=instance;
				if(null==sc){
					synchronized (SingletonPatternDoubleCheckLock.class) {
						if(null==sc){
							sc=new SingletonPatternDoubleCheckLock();
						}
					}
					instance=sc;
				}
			}
		}
		return instance ;
	}

	// 私有化构造器
	private SingletonPatternDoubleCheckLock() {
	}

}

4、静态内部类实现单例模式

特点:线程安全,兼备并发高效调用和延迟加载的优势。

代码:

package com.zwh.gof23;

/**
 * 静态内部类实现单利模式
 * 1、只有调用全局访问方法时,才会初始化单例对象。可以延迟加载
 * 2、加载类时线程安全
 * 3、同时具备懒汉式和饿汉式的优势
 * 
 * @author zwh
 * 
 */
public class SingletonPatternInnerStaticClass {

	/**
	 * 静态内部类中声明并初始化外部类的实例
	 * 
	 * @author zwh
	 * 
	 */
	private static class SingletonClassInstance {
		private static final SingletonPatternInnerStaticClass instance = 
				new SingletonPatternInnerStaticClass();
	}

	/**
	 * 全局获取单例的方法
	 * 
	 * @return
	 */
	public static SingletonPatternInnerStaticClass getInstance() {
		return SingletonClassInstance.instance;
	}

	/**
	 * 构造方法私有化
	 */
	private SingletonPatternInnerStaticClass() {
	}
}

5、使用枚举实现单例模式

特点:实现简单,枚举本身就是单例模式,无延迟加载

实现代码:

package com.zwh.gof23;
/**
 * 使用枚举实现单例模式
 * @author zwh
 * 1、调用效率高
 * 2、避免反射漏洞
 * 3、没有延迟加载
 */
public enum SingletonPatternEnum {

	/**
	 * 定义一个元素,代表一个实例
	 */
	INSTANCE;
	
	/**
	 * 对枚举元素的操作
	 */
	public void singletonOperation(){
		
	}
}

三、测试

对上面的单利模式的实现进行测试,通过对比分别初始化的两个对象是否为同一个对象。代码如下:

package com.zwh.gof23.singleton;

/**
 * 单例模式测试类
 * @author zwh
 *
 */
public class TestClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		testSingletonPatternStaving();
		testSingletonPatternSlaker();
	}
	
	/**
	 * 测试饿汉式单利模式
	 */
	private static void testSingletonPatternStaving(){
		SingletonPatternStarving s1=SingletonPatternStarving.getInstance();
		SingletonPatternStarving s2=SingletonPatternStarving.getInstance();
		System.out.println(s1==s2);
	}
	
	
	/**
	 * 测试懒汉式单例模式
	 */
	private static void testSingletonPatternSlaker(){
		SingletonPatternSlacker s1=SingletonPatternSlacker.getInstance();
		SingletonPatternSlacker s2=SingletonPatternSlacker.getInstance();
		System.out.println(s1==s2);
		
	}

}

输出均为true。

四、小结

实现单例模式当然肯定不仅仅是这5种方法,最重要的是要将设计模式运用在日常工作中。学以致用才是学习的目的。

关于选用哪一种方式,不需要延迟加载时,枚举式>饿汉式

需要延迟加载时:静态内部类方式>懒汉式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云间歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值