设计模式(四)单例模式

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

例子: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() 创建唯一实例。再次调用将返回第一次创建的实例。

设计模式(四)单例模式_第1张图片

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


优点:

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

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

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


缺点:

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

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

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


适用场景:

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

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

你可能感兴趣的:(设计模式)