设计模式--单列模式

一、简介

1、单列模式的定义

单列模式属于 #创建型模式# ,确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。

2、三个要点

(1)某个类只能有一个实例;

(2)它必须自行创建这个实例;

(3)它必须自行向整个系统提供这个实例。

二、实现与测试

1、饿汉单列

public class SingletonEager {

	// 无论是否使用都初始化对象,浪费内存
	private static final SingletonEager INSTANCE = new SingletonEager();

	private SingletonEager(){}

	public static SingletonEager getInstance() {
		return INSTANCE;
	}

}

public class SingletonEagerTest {

	@Test
	@DisplayName("饿汉式单列对象相等")
	void SingletonEagerObjectEqual() {
		SingletonEager eagerOne = SingletonEager.getInstance();
		SingletonEager eagerTwo = SingletonEager.getInstance();
		Assertions.assertEquals(eagerOne, eagerTwo);
	}

}

优点:初始化就实例化对象,后续直接使用对象,性能高

缺点:无论是否使用对象都会默认初始化,在不需要使用的时候会浪费内存资源

2、懒汉单列

public class SingletonLazy {

	// volatile 屏蔽jvm优化,性能低
	private volatile static SingletonLazy INSTANCE = null;

	private SingletonLazy(){}

	public static SingletonLazy getInstance(){
		if (null == INSTANCE){
			// 重量级锁,性能低
			synchronized (SingletonLazy.class){
				// double check
				if (null == INSTANCE){
					INSTANCE = new SingletonLazy();
				}
			}
		}
		return INSTANCE;
	}

}

public class SingletonLazyTest {

	@Test
	@DisplayName("懒汉式单列对象相等")
	void SingletonLazyObjectEqual(){
		SingletonLazy lazyObjectOne = SingletonLazy.getInstance();
		SingletonLazy lazyObjectTwo = SingletonLazy.getInstance();
		Assertions.assertEquals(lazyObjectOne, lazyObjectTwo);
	}

}

优点:按需使用,需要用到对象的时候再去实例化,节约资源

缺点:性能较差,并发情况下需要等待锁释放

3、IoDH单列(最佳单列)

public class SingletonExample {

	private SingletonExample(){}

	private static class HolderClass{
		private static final SingletonExample instance = new SingletonExample();
	}

	public static SingletonExample getInstance(){
		return HolderClass.instance;
	}

}

public class SingletonExampleTest {

	@Test
	@DisplayName("单列对象相等")
	void ObjectEqual(){
		SingletonExample objectOne = SingletonExample.getInstance();
		SingletonExample objectTwo = SingletonExample.getInstance();
		Assertions.assertEquals(objectOne,objectTwo);
	}

}

优点:Initialization on Demand Holder

缺点:与编程语言本身的特性相关,很多面向对象语言不支持IoDH

三、总结

1、优点

(1)单例模式提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它。

(2)由于在系统内存中只存在一个对象,因此可以节约系统资源。对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。

(3)允许可变数目的实例。基于单例模式,开发人员可以进行扩展,使用与控制单例对象相似的方法来获得指定个数的实例对象,既节省系统资源,又解决了由于单例对象共享过多有损性能的问题。(注:自行提供指定数目实例对象的类可称之为多例类。)

2、缺点

(1)由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。

(2)单例类的职责过重,在一定程度上违背了单一职责原则。因为单例类既提供了业务方法,又提供了创建对象的方法(工厂方法),将对象的创建和对象本身的功能耦合在一起。

(3)现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收技术,因此,如果实例化的共享对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致共享的单例对象状态的丢失。

3、适用场景

(1)系统只需要一个实例对象。例如,系统要求提供一个唯一的序列号生成器或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。

(2)客户调用类的单个实例只允许使用一个公共访问点。除了该公共访问点,不能通过其他途径访问该实例。

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值