A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© liii 中级黑马   /  2015-6-29 13:20  /  856 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 liii 于 2015-6-29 14:26 编辑

单例,即单一实例,也就是一个类只允许有一个实例(即,一个对象)
那单例到底用在哪儿呢?,说实话这个我也没理解,感受不到它的用途,相信在以后接触到项目之后,才能真正体会,但是这不影响我们先学会简单的去实现它。

1,创建一个对象有几种方法呢?
    1, Person *p = [Person new]; // 第一种方式
    2, Person *pp = [[Person alloc] init]; // 第二种方式
    3, Person *ppp = [p copy] ; // 第三种方式 (记得要要让Person类先,遵守NSCoping协议)

2,这样创建的对象是几个对象呢?
    // 打印输出,看地址是否为同一个,不同则为不同对象,相同则为同一对象
    * NSLog(@"\n p = %p \n pp = %p \n ppp = %p", p, pp, ppp);

3, 答案
    * new 和 alloc 创建的是不同的新对象,地址不同
    * copy 创建的对象ppp 与 pp 对象 是同一个对象,地址相同

4,单例的思想
    * 把创建对象的方法重写,让别人在通过这些方法创建对象的时候,都获取已经存在的对象
    * 问题来了,已经存在的对象由谁来提供呢,答案:类本身(通过类方法,自己创建自己的对象)
    * 给外界只提供一个获取它的方法,像是set方法一样,你要使用我的成员变量,只能使用我的方法
    * 这是有个前提的,成员变量需要私有化,不允许别人继承,也不允许直接访问,我对外提供的接口只有一个set方法和get方法

5,问题又来了,怎么实现由类本身提供对象,又怎么通过方法给外界一个获取它的接口呢
    // 代码举例:比如有一个Car类,在实现文件中注意

#import <Foundation/Foundation.h>

// 第一步
static Car *shareInstance = nil;
/** 上边这一行,是干什么呢?
    * 声明一个Car类型的指针,用来接收对象,为什么要放在这个位置呢?
    * 让它变成私有的,只局限于在这个文件中使用,不让它在main函数内使用,如果写在@interface中,只要引入头文件就可以用了
    * 那为什加 static 呢? 答:为了让指针里的地址值,不会被清空(就像在代码块内用static修饰 变量n,代码块结束而n的值还会保留一样)
*/  

@implementation Car

// 第二步
+ (instancetype)shareInstance{ // 自己提供给外界一个获取对象的方法(接口)
   
    if(shareInstace == nil){ // 如果是第一次创建对象,就创建一个对象
        shareInstance = [[self alloc] init]; // 自己创建一个对象赋值给,自己定义的指针,完成对象在,类本身内的创建
        return shareInstance; // 将创建好的对象返回
    }
    return = shareInstance; // 如果已经存在对象(指向对象的指针不为空),则直接返回已经创建好的对象
}

/** 第三步:覆盖掉alloc 方法,copy方法
    * 了解一个过程
    * 通过 new 或 alloc 方法创建对象的时候,其实是调用了一个类方法
    * 即 + (instancetype)allocWithZone:(NSZone *)zone;
    * 所以重写它,在方法内部,让他直接放回类已经创建好的对象
    * 通过 copy 创建对象的时候,实际是调用了一个 对象方法
    * 即 - (instancetype)copyWithZone:(NSZone *)zone;
    * 所以也重写它,每当copy的时候,也让他返回已经创建好的对象
*/
+ (instancetype)allocWithZone:(NSZone *)zone{
    @synchronized(self){ // 线程保护,固定格式,记住写法即可
        if(shareInstace == nil)}{ // 判断是否已经存在新对象
            shareInstance = [super allocWithZone:zone]; // 如果不存在,则创建一个新对象
            return shareInstance; // 返回刚创建好的对象给调用者
        }
        return shareInstance; // 如果存在则直接返回已经创建好的对象
    }
}

- (instancetype)copyWithZone:(NSZone *)zone{

    return self; // 当copy对象的时候,直接返回已经存在的对象
}

@end


/** 第五步
    * main函数内创建对象验证,他们是否指向同一个对象(即,内存地址一样)
    * 1,通过 类提供给外界的方法 + (instancetype)shareInstance; 创建一个对象
    * 2,通过new方法创建一个对象
    * 3,通过alloc方法创建一个对象
    * 4,通过copy方法创建一个对象
*/

#import <foundation/Foundation.h>
#import "Car.h"

int main()
{
    Car *c = [Car shareInstance];
    Car *cc = [Car new];
    Car *ccc = [[Car alloc] init];
    Car *cccc = [ccc copy];

    NSLog(@"\n %p \n %p \n %p \n %p", c, cc, ccc, cccc); // 查看地址是否相同,相同即实现了单一实例

    retun 0;
}
   
/** 总结:实现单例的步骤
1,在@implementation文件内创建一个 静态的私有的空的所属类的类型的指针
代码:static Car *shareInstance = nil;
2,提供一个能够自己创建对象的类方法
代码: + (instancetype)shareInstance;
3,重写alloc方法
4,重写copy方法
5,在main函数内创建对象验证

*/

评分

参与人数 2黑马币 +12 收起 理由
yi95392 + 6 很给力!
杨宇俊 + 6 赞一个!

查看全部评分

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马