设计模式(四)单例模式

单例模式是一种常用的软件设计模式,旨在确保一个类只有一个实例,并提供全局访问点。它常用于资源管理和唯一标识的任务,如Windows任务管理器。单例模式通过私有构造函数和静态 getInstance 方法来防止外部直接实例化。尽管有节约资源、控制访问等优点,但也存在扩展困难和违背单一职责原则等缺点。适用场景包括系统只需要一个实例的情况以及需要统一公共访问点的场景。
摘要由CSDN通过智能技术生成

对于一各软件系统的某些类而言,无需创建多个实例。

例子:Windows任务管理器,无论启动任务管理器多少次,系统始终只能弹出一个任务管理器窗口。

为了节约系统资源,以及保证信息的唯一性,有时需要确保系统中某个类只有唯一的实例。当这个唯一实例创建后无法再创建同一类型的其他实例。

这就是单例模式的动机。


示例:TaskManager类

(1)为确保实例唯一性,禁止类的外部直接使用new来创建对象:将TaskManager的构造函数的访问权限设为private

private TaskManager() { ... }

(2)TaskManager类内部还是可以创建对象的,可在TaskManager类内部创建并保存这一唯一实例,为了让外界能够访问这个唯一实例,需要在TaskManager类中定义一个静态的TaskManager类型的私有成员变量。

private static TaskManager tm = null;

(3)为保证成员变量的封装性,将TaskManager类型的tm对象的可见性设置为private,并增加静态方法getInstance()来让外界使用该成员变量tm以及实例化tm

public static TaskManager getInstance()
{       // 如果存在对象实例,直接返回已有的tm对象
	if(tm == null){ //如果尚未存在该类型的唯一实例
		tm = new TaskManager();//自行实例化
	}
	return tm; 
}
TaskManager是一个单例类。
使用static方法:静态方法,在类外可以直接通过类名来访问,而无需创建TaskManager对象。事实上,在类外也无法创建TaskManager对象,因为构造函数是私有的。

问题:为什么要将成员变量tm定义为静态变量呢?原因在于C++对于静态成员函数的限制,静态成员函数只能访问静态成员,不能访问非静态成员函数和非静态数据成员。但是非静态成员函数能够访问任意的静态方法和静态成员。另外,因为tm是TaskManager类型的静态对象,是属于这个类型的,可作为供外部共享访问的唯一实例。

可以通过TaskManager::getInstance() 创建唯一实例。再次调用将返回第一次创建的实例。


如果一个单例类Singleton,它应该是:在单例类的内部实现只生成一个实例,同时它提供一个静态GetInstance()方法,让客户可以访问它的唯一实例;为了防止在外部对单例类实例化,它的构造函数都可见性设为private;在单例类内部定义了一个Singleton类型的静态对象,作为供外部共享访问的唯一实例。


优点:

(1)提供了对唯一实例的受控访问。严格控制客户如何访问以及何时访问它。

(2)节约系统资源,对于频繁创建和销毁的对象,可以显著提高系统性能。

(3)允许可变数目的实例(多例类),实现方法类似于单例类。既节约系统资源,又解决了单例对象共享过多有损性能的问题。


缺点:

(1)单例类没有抽象层,扩展困难。

(2)单例类指责过重,一定程度违背了单一职责原则。

(3)很多面向对象语言(Java ,c#)提供自动垃圾回收技术,如果实例化对象长时间不被利用,系统会认为是垃圾而自动销毁并回收资源,下次利用又重新实例化,导致共享的单例对象状态丢失。


适用场景:

(1)系统只需要一个实例对象。功能要求,或者考虑资源消耗太大。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值