Java开发中的23中设计模式详解(一)创建型模式之单例模式

设计模式一共有23种,分为三大类

创建型模式:
单例模式,工厂模式,抽象工厂模式,原型模式
结构型模式:
适配器模式,桥接模式,装饰器模式,组合模式,外观模式,享元模式,代理模式
行为型模式:
模板方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,策略模式,责任链模式,访问者模式

这23种设计模式本质上是对Java面向对象原则实际运用,这23种设计模式更多是为了提高代码的可读性、可复用性、可维护性、稳健性以及安全性。让我们写出的代码更加整洁。

一、创建型模式

单例模式:

最重要的作用:保证类只有一个实例,并且提供一个访问该实例的全局访问点。

常见的五种实现单例模式的方法
主要:

  • 饿汉式(线程安全,调用效率高,但不能延迟加载,资源利用效率低)
  • 懒汉式(线程安全,调用效率不高,可以延迟加载,可以真正用时再创建,方法实现了同步,调用效率低)

其他:

  • 双重检测锁(线程安全,调用效率低,可以延迟加载,偶尔会出问题)
  • 静态内部类(调用效率高,可以延迟加载)
  • 枚举单例(调用效率高,不可以延迟加载,可以避免反射和反序列化重新创建多个实例)
1、饿汉式实现
public class HungryMan {	
	//类初始化时立即加载这个对象
	private static HungryMan instance=new HungryMan();
	 //私有化的构造器
	private HungryMan() {
	}
	//对外开放的获取唯一实例的方法
	public static HungryMan getInstance() {
		return instance;
	}
}
class Demo06{
	public static void main(String args[]) {
		//无法通过new获得该对象的实例
		//HungryMan instance=new HungryMan();
		//只能通过对外提供的方法获取该对象的唯一实例
		HungryMan instance1=HungryMan.getInstance();
		HungryMan instance2=HungryMan.getInstance();
		//多次获取的实例时,本质上是同个实例
		System.out.println(instance1);
		System.out.println(instance2);

	}
}
csdn.HungryMan@7852e922
csdn.HungryMan@7852e922

类在加载时,线程时天然安全的,static变量在会在类加载时初始化。此时不会涉及多个多线程对象的访问的情况,故可以省去synchronized关键字。

缺点:如果只是加载该对象,而不是需要获取该对象的实例,会造成资源的浪费。
2、懒汉式实现
public class LazyMan {
	private static LazyMan instance;
	private LazyMan() {
	}
	//使用了同步,但是效率低了
	public static synchronized LazyMan getInstance() {
		if(instance==null) {
			instance= new LazyMan();
			return instance;
		}
		return instance;
	}
}
class Demo07{
	public static void main(String args[]) {
		//无法通过new获得该对象的实例
		//LazyMan instance=new LazyMan();
		//只能通过对外提供的方法获取该对象的唯一实例
		LazyMan instance1=LazyMan.getInstance();
		LazyMan instance2=LazyMan.getInstance();
		//多次获取的实例时,本质上是同个实例
		System.out.println(instance1);
		System.out.println(instance2);
	}
}
csdn.LazyMan@7852e922
csdn.LazyMan@7852e922
缺点:与饿汉式相比,可以延迟的获取该对象的实例,但是获取实例时,都需要同步,使并发效率低了。
3、双重检查锁实现
public class DoubleCheck {
	private static DoubleCheck instance=null;	
	private DoubleCheck() {
	}	
	//方法同步 调用效率低
	public static synchronized DoubleCheck getInstance() {
		if(instance==null) {
			DoubleCheck d;
			synchronized(DoubleCheck.class) {
				d=instance;
				if(d==null) {
					synchronized(DoubleCheck.class) {
						if(d==null) {
							d=new DoubleCheck();
						}
					}
					instance=d;
				}
			}
		}
		return instance;
	}
}

class Demo08{
	public static void main(String args[]) {
		//无法通过new获得该对象的实例
		//DoubleCheck instance=new DoubleCheck();
		//只能通过对外提供的方法获取该对象的唯一实例
		DoubleCheck instance1=DoubleCheck.getInstance();
		DoubleCheck instance2=DoubleCheck.getInstance();
		//多次获取的实例时,本质上是同个实例
		System.out.println(instance1);
		System.out.println(instance2);

	}
}
csdn.DoubleCheck@7852e922
csdn.DoubleCheck@7852e922

缺点:使用了同步方法,效率变低了,由于编译器优化和JVM底层内部模型原因,有时会出错,不建议使用。

4、静态内部类
public class StaticInsideClass {
	//静态内部类
	private static class StaticInside{
		//static final 保证了内存只有一个实例存在
		private static final StaticInsideClass instance=new StaticInsideClass();
	}
	private StaticInsideClass() {
	}
	public static StaticInsideClass getInstance() {
		return StaticInside.instance;
	}
}
class Demo09{
	public static void main(String args[]) {
		//无法通过new获得该对象的实例
		//StaticInsideClass instance=new StaticInsideClass();
		//只能通过对外提供的方法获取该对象的唯一实例
		StaticInsideClass instance1=StaticInsideClass.getInstance();
		StaticInsideClass instance2=StaticInsideClass.getInstance();
		//多次获取的实例时,本质上是同个实例
		System.out.println(instance1);
		System.out.println(instance2);
	}
}
csdn.StaticInsideClass@7852e922
csdn.StaticInsideClass@7852e922
外部类没有static属性,不会立即加载对象,同时兼备效率高和延迟加载的优势
5、枚举单例
public enum EnumInstance {
	// 没有延迟加载
	// 避免反射和反序列化这个漏洞
	// 这个枚举元素本身就是单例对象
	INSTANCE;
	// 添加自己需要的操作
	public void Operation() {
	}
}
class Demo10{
	public static void main(String args[]) {
		EnumInstance instance1=EnumInstance.INSTANCE;
		EnumInstance instance2=EnumInstance.INSTANCE;		
		System.out.println(instance1);
		System.out.println(instance2);
	}
}
INSTANCE
INSTANCE
枚举本身就是单例模式,实现简单,可以避免反射和反序列化,但是不能够延迟加载

有兴趣的自行测一下这五种方法生成实例的效率。这里就不做测试。

在需要实现单例模式时,如果单例对象占用资源少,不需要延迟加载,则使用枚举式大于饿汉式
若单例对象占用资源多,需要延迟加载,则使用静态内部类大于懒汉式

以上就是对关于23种设计模式中的单例模式进行了了解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值