JAVA设计模式(一)设计模式之单例设计模式

前言

      熬过了前面的那些磕磕绊绊,我们正式进入到java的精髓,设计模式的讲解,本章来尝鲜单例设计模式

范例

1.单例设计模式的作用

保证一个类只有一个实例,并且提供一个访问该实例的全局访问点

  • 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决
  • 单例模式可以在系统设置全局的访问点,优化共享资源访问。例如:可以设计单例类来负责所有数据表的映射处理

2.常见的单例模式设计方法 

  • 饿汉式(线程安全、调用效率高,但不能延时加载)
package com.jwang.test;

public class RegexTest {

	public static void main(String[] args) {
		System.out.println(Singleton.getInstance()==Singleton.getInstance());
	}
}

//饿汉式实现单例
class Singleton{
	private static Singleton singleton = new Singleton();//类初始化立刻加载类对象
	
	private Singleton(){}//构造器私有化
	
	//供外部获取该类实例
	public static Singleton getInstance(){
		return singleton;
	}
}
  • 懒汉式(线程安全、调用效率不高,但是可以延时加载) 
package com.jwang.test;

public class RegexTest {

	public static void main(String[] args) {
		System.out.println(Singleton.getInstance()==Singleton.getInstance());
	}
}

//懒汉式实现单例
class Singleton{
	private static Singleton singleton;
	
	private Singleton(){}//构造器私有化
	
	//供外部获取该类实例
	public static synchronized Singleton getInstance(){
		if(singleton == null){
			singleton = new Singleton();
		}
		return singleton;
	}
}

以上是常见的两种单例模式的实现方式!


通过分析可以得出结论:上面两种单例的实现方式各有优缺点,下面介绍几种其他的单例实现优化上面的实现方式!

  • 双重检测锁实现(不建议使用)

我们知道,懒汉式的实现方式是在获取实例的时候,获取实例的方法加上了synchronized关键字来确保线程安全!但是带来的问题却是执行效率的低下!

双重检测锁模式将同步的功能放入方法的实现当中,只需要第一次同步创建对象之后就无需同步了,大大的提高了执行效率,又实现了懒加载!

通用实现代码如下:

public class SingletonDemo03 {
	private static SingletonDemo03 instance = null;

	public static SingletonDemo03 getInstance() {
		if (instance == null) {
			SingletonDemo03 sc;
			synchronized (SingletonDemo0.class) {
				sc = instance;
				if (sc == null) {
					synchronized (SingletonDemo03.class) {
						if (sc == null) {
							sc = new SingletonDemo03();
						}
					}
					instance = sc;
				}
			}
		}
		return instance;
	}

	private SingletonDemo03() {
	}
}

由于编译器优化原因和JVM底层内部模型原因,偶尔会出问题。不建议使用!

  • 静态内部类实现 (常用,稳定)

由于双重检测锁实现方式存在诸多的问题,这里提出了静态内部类的实现方法,更好的兼顾懒汉和饿汉的优点!

实现代码如下:
 

public class SingletonDemo04 {
	private static class SingletonClassInstance {
		private static final SingletonDemo04 instance = new SingletonDemo04();
	}

	public static SingletonDemo04 getInstance() {
		return SingletonClassInstance.instance;
	}

	private SingletonDemo04() {
	}
}

要点:

  1. 外部类没有static属性,则不会像饿汉式那样立即加载对象。
  2. 只有真正调用getInstance(),才会加载静态内部类。加载类时是线程安全的。
  3. instance是static final类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性.
  4. 兼备了并发高效调用和延迟加载的优势!

 

  • 枚举方式实现

该种实现比较容易,利用了枚举类型本身的单例化特性!

public enum SingletonDemo05 {
	INSTANCE;
	
	public void play(){
		//other operation
	}
	
	public static void main(String[] args) {
		SingletonDemo05 singletonDemo05 = SingletonDemo05.INSTANCE;
		System.out.println(singletonDemo05);
	}
}

优点:
– 实现简单
– 枚举本身就是单例模式。由JVM从根本上提供保障!避免通过反射和反序列化的漏洞!
缺点:
– 无延迟加载



总结:

单例模式有五种实现方式,你除了要知道懒汉和饿汉,你还要知道其余其他实现方式,面试会大大加分!

  1. 饿汉实现方式:实例化对象耗费资源不大且无需懒加载可以使用,执行效率高
  2. 懒汉实现方式:需要懒加载或实例化对象消耗资源大可以使用,但执行效率低
  3. 双重检测锁实现方式:由于内部原因,不推荐使用,了解即可
  4. 静态内部类实现方式:如果需要懒加载又要考虑执行效率,选择该种实现方式再好不过啦
  5. 枚举实现方式:如果不需要懒加载,优先选用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值