静态变量和单例模式

静态变量和单例模式

1.静态变量

静态变量Static Variable)在计算机编程领域指在程序执行前系统就为之静态分配(也即在运行时不再改变分配情况)存储空间的一类变量。与之相对应的是在运行时只暂时存在的自动变量(即局部变量)与以动态分配方式获取存储空间的一些对象,其中自动变量的存储空间在调用栈上分配与释放。

不同情况下的作用

除明确标识出变量的生命周期外,将变量声明为static存储类还会根据变量属性不同而有一些特殊的作用:

  • 对于静态全局变量来说,针对某一源文件的以static声明的文件级变量与函数的作用域只限于文件内(只在文件内可见),也即“内部连接”,因而可以用来限定变量的作用域;
  • 对于静态局部变量来说,在函数内以static声明的变量虽然与自动局部变量的作用域相同(即作用域都只限于函数内),但存储空间是以静态分配而非默认的自动分配方式获取的,因而存储空间所在区域不同(一般来说,静态分配时存储空间于编译时在程序数据段分配,一次分配全程有效;而自动分配时存储空间则是于调用栈上分配,只在调用时分配与释放),且两次调用间变量值始终保持一致;
  • 对于静态成员变量来说,在C++中,在类的定义中以static声明的成员变量属于类变量,也即在所有类实例中共享,与之相对的就是过程变量。

C示例

在C语言中,带有静态变量的程序如下所示:

#include <stdio.h>
 
void func() {
    static int x = 0; // 在对func的三次调用中,x只进行一次初始化
    printf("%d
", x); // 输出x的值
    x = x + 1;
}
 
int main(int argc, char * const argv[]) {
    func(); // 输出0
    func(); // 输出1
    func(); // 输出2
    return 0;
}

2.单例模式

  一个单例的类,无论一个应用请求它多少次,都将返回一个相同的实例。一个典型的类允许调用者创建很多实例,而对于单例类来说,一个进程中只能有一个类的实例。一个单例对象提供了全局访问其类的资源的点。单例常被用在这种单点控制被满足的情况下,例如一些类需要提供公用的服务或者资源。

 

你应该从一个单例类的工厂方法中获得一个全局实例。当第一次被请求的时候这个类应该懒加载一个唯一的实例,并且保证之后没有其他实例被创建。。一个单例类同时也组织调用者对它实例进行copying,retaining,或者releasing。

在一些Cocoa的框架中用到单例。其中有,NSFileManager,NSWorkspace。在UIKit,UIApplication 和 UIAccelerometer也用到单例。工厂方法以sharedClassType这种名字,方便的返回一个单例对象。例如,在Cocoa框架中,sharedFileManager,sharedColorPanel,sharedWorkspace。

 

 3. IOS中单例的创建

  有了上面的知识,我们就比较容易理解单例的创建方式了。首先介绍两种单例的创建方式。

static AccountManager *DefaultManager = nil;
 
+ (AccountManager *)defaultManager {
    if (!DefaultManager) DefaultManager = [[self allocWithZone:NULL] init];
    return DefaultManager;
}

在iOS4之后有了另外一种写法:

+ (AccountManager *)sharedManager
{
        static AccountManager *sharedAccountManagerInstance = nil;
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
                sharedAccountManagerInstance = [[self alloc] init]; 
        });
    return sharedAccountManagerInstance;
}

  无论上面的方法被调用几次,静态变量总初始化一次。关于dispatch_once这个方法,官方是这样说的:在一个应用的生命周期中执行一个block对象一次且仅一次。predicate参数是一个指向dispatch_once_t结构的指针,用来判断block有没有被完成执行。block参数是那个被执行一次的块。dispatch_once这个函数对于初始化一个应用中的全局数据如单例是很有用的。在使用block块中初始化的变量的时候,需要首先调用这个函数。如果在多线程情况下同时调用,这个函数同步等待block块中的内容执行完毕。predicate必须指向一个全局或静态变量。 

原文地址:https://www.cnblogs.com/wantyoulee/p/4390715.html