在软件世界里面,单实例是一个非常重要的概念。比如
一个国家只有一个主席/总统/...
一支军队只有一个最高统帅
一个班级只有一个班主任
...
OpenHarmony中是如何实现和使用上述概念的呢?本文分别从C语言和C++语言的角度,分别用一个例子来进行观察和分析。
struct **HdfObject** * **DriverInstallerCreate** (void)
{
static **bool** **isDriverInstInit** = false;
static struct **DriverInstaller** driverInstaller;
if (! **isDriverInstInit** ) {
**DriverInstallerConstruct** (&driverInstaller);
**isDriverInstInit** = true;
}
return (struct **HdfObject** *)&driverInstaller;
}
如上代码所述,DriverInstaller类型的对象仅有一份,名称为driverInstaller, 用static修饰,则其数据存储在全局数据区(不在栈空间),并且首次调用的时候isDriverInstInit为false, 会进行初始化动作(DriverInstallerConstruct),后续调用不再重复初始化,直接返回driverInstaller的地址即可。
上述C语言代码通过将变量限定在DriverInstallerCreate函数内,使得要访问driverInstaller变量必须调用这个函数,通过static限制了变量所对应的数据只会存在一份,且在程序加载成功后,变量位于固定的位置,其生命周期与程序保持一致,从而最终达到单实例以及便利访问的效果。
有一种变通的做法是将变量从函数内移动到函数外,使得其成为C语言源代码文件内的公共变量,这种做法扩大了变量的可见范围,虽然也能实现单实例变量,但不是最佳的编程实践,因为这种做法导致文件内的多个函数都可以直接访问变量,不利于未来的维护和修订。例如,当新增一个需求(统计变量被哪些模块访问), 这种变通做法修改起来要困难一些。
class **ObjectCollector** {
public:
...
static **ObjectCollector** & **GetInstance** ();
...
private:
**ObjectCollector** () = default;
**...**
};
**ObjectCollector** & **ObjectCollector** :: **GetInstance** ()
{
static **ObjectCollector** mapper;
return mapper;
}
上述代码中ObjectCollector类型的对象只能通过其GetInstance()方法获取到。原因是其构造函数声明成了private(外部无法使用),而GetInstance()方法属于ObjectCollector类型自身的方法,可以使用。
且GetInstance()方法中定义的对象使用static修饰,其生存期与程序一致,可见性仅为方法内,与C语言做法类似,通过这个小技巧达到约束ObjectCollector只能产生一个实例的效果。
GetInstance返回的是对象的引用,而对象的构造函数为私有的,并且在GetInstance函数中定义成static对象,所以,系统加载GetInstance的时候,就会调用对应的构造函数来构造对象,后续调用GetInstance的时候直接返回此对象,所以系统中只会有1个此类型的对象。
本文件简述了单实例的基本知识及其应用场景,并以OpenHarmony中的代码为例分别从C和C++语言角度来分析和学习单实例模式。
单实例模式在软件设计中应用非常广泛,熟悉并掌握对学习和理解软件开发知识非常有帮助。
更多回帖