美文网首页
Objective-C之原型模式

Objective-C之原型模式

作者: 小帅798 | 来源:发表于2017-12-22 17:22 被阅读0次

    原型模式

    原型模式是非常简单的一种模式,在我们的实际开发中经常用到这种模式,例如你创建的可变字典、可变字符串调用copy来生成新的对象,那么你在这个过程中已经使用了原型模式。还有比如你在写论文的时候,给老师交的初稿,退回来之后再修改你肯定不是在初稿上修改的,也不是再从新敲一遍,而是复制一份初稿再修改,这个拷贝初稿生成终稿的过程就叫原型模式。

    举个例子:你创建了一个Student类,属性有性别sex、名字name、年级className、班主任teacher、年龄years。然后开始创建学生对象:小江、小帅、小虎等多个对象,在创建的过程中发现这些人是同班学生、除了性别和名字有差别之外其他的信息基本一样,如果初始化这些学生对象然后给每个属性赋值,显然这些代码都是重复性的代码。so通过让Student类遵守NSCopying的协议,就能通过copy快速的初始化对象,然后根据差异简单的改变sex和那么即可。(ps:例子只是为了说明这种模式,相信大家还有很多更好的办法,我现在在学习GoF的《Objective-C的编程之道,iOS设计模式解析》所以现在以简书的形式来做个笔记供大家相互学习和指正,之后会不断的将在这本书理解到的东西转到简书上)

    原型模式的定义:使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象。《设计模式》(Addison-Weslet,1994)

     何时使用原型模式:

            1、需要创建的对象应独立于其类型与创建方式。

            2、要实例化的类是在运行时决定的。

            3、不想要与产品层次相对应的工厂层次。

            4、不同类的实例间的差异仅是状态的若干组合。因此复制相应数量的原型比手工实例化更加方便。

            5、类不容易创建,比如每个组件可把其他组件作为子节点的组合对象。复制已有的组合对象并对副本进行修改会更加容易。

    在GoF的书中有句话很好:从功能的角度来看,不管什么对象,只要复制本身比手工实例化要好,那么都可以是原型对象。使用设计模式更像艺术行为而非科学行为。

    深拷贝&浅拷贝

    浅拷贝:只是复制指针,且复制的指针的指向还是原来的内存资源,并没有在内存中开辟新的资源,和原来的指针指向一块内存资源。

    深拷贝:不但拷贝了指针,而且也将原指针指向的资源进行了拷贝,相当于开辟了新的内存,把原来的资源也拷贝了一份并且各自的指针指向各自的资源。

    Coco Touch 框架中根类(NSOblect)的衍生类提供了实现深复制的协议(NSCopying)。NSObject有一个实例方法(id)copy,这个方法默认调用了[self copyWithZone:nil],对于引用了NSCopying协议的子类,必须实现(id)copyWithZone:(NSZone *)zone方法,否则将引发异常。(输出如下)

    assign&copy&retain

    直接看例子

    @interface IDStudent : NSObject

    @property (assign, nonatomic, getter=isMale)BOOL male;

    @property (copy, nonatomic)NSString *name;

    @property (copy, nonatomic)NSString *className;

    @property (copy, nonatomic)NSString *teacher;

    @property (assign, nonatomic)NSUInteger years;

    @property (assign, nonatomic)NSMutableString *name1;

    @property (retain, nonatomic)NSMutableString *name2;

    @property (copy, nonatomic)NSMutableString *name3;

    + (instancetype)studentWithName:(NSString *)name male:(BOOL)male className:(NSString *)className teacher:(NSString *)teacher yeas:(NSUInteger)years;

    @end

     NSMutableString *str =[NSMutableString stringWithFormat:@"小帅"];   

    IDStudent *student =[IDStudent new];    

    student.name1 =str;    

    student.name2 =str;    

    student.name3 =str;         

    NSLog(@"\n str的地址:%p\n name1的地址:%p(assign) \n name2的地址:%p(retain)\n name3的地址:%p(copy)\n",str,student.name1,student.name2,student.name3);

    输出结果

    str的地址:0x60c000240e10

    name1的地址:0x60c000240e10(assign)

    name2的地址:0x60c000240e10(retain)

    name3的地址:0x60c000036760(copy)

    结论:

    解析一下代码:NSMutableString *str =[NSMutableString stringWithFormat:@"小帅"];

    1、在栈区开辟内存来存str,比如地址为:0xFFFF,内容为0x60c000240e10

    2、在堆区开辟内存来存str的内容@"小帅",地址为0x60c000240e10,内容为@"小帅"

    assing:如果在MRC的情况下打印retainCount,它的值不会加1,(自己可以试试),且在堆区的地址还是和str的地址一样,说明assign只是一个str的影子

    retain:这个接触到MRC的情况下,它的值会加1,虽然它的地址还是和str的一样,但是它会在栈区开辟新的空间比如0xWWWW,但是内容还是0x60c000240e10相当于经过retain的name2在栈区开辟了新的空间,都是强指向在堆区地址为0x60c000240e10的内容,共同管理。

    copy:使用copy后堆区的地址改变,说明这个过程在栈区开辟了新的空间地址为0xBBBB,储存的内容为0x60c000036760同样也在堆区开辟了新的空间,地址为:0x60c000036760内容为@“小帅”。跟原来的str没有了关系,说明进行了深拷贝。

    下边对NSString在进行一下实验,看是否和NSMutableString一样的储存方式

    NSString *name =[NSString stringWithFormat:@"name"];    

    NSString *nameCopy =[name copy];    

    NSMutableString *mName =[name mutableCopy];    

    NSLog(@"\nname:%p\nnameCopy:%p\nmName:%p\n",name,nameCopy,mName);         

    NSMutableString *str =[[NSMutableString alloc]initWithString:@"test"];    

    NSMutableString *copyStr =[str copy];    

    NSLog(@"\n------------------------------------\nstr:%p\ncopyStr:%p",str,copyStr);

    输出结果:

    2017-12-22 16:34:02.566672+0800 desgin_原型模式[25958:11425087]

    name:0xa000000656d616e4

    nameCopy:0xa000000656d616e4

    mName:0x60c00024c360

    2017-12-22 16:34:02.566808+0800 desgin_原型模式[25958:11425087]

    ------------------------------------------------------------------------

    str:0x60c00024ca50

    copyStr:0xa000000747365744

    结论:根据输出结果NSString的不可变字符串在copy的情况地址一致,由于copy返回的是不可变副本,系统只生成一份内存资源,此时的copy只是浅拷贝,和retain作用一样。

    通过mutableCopy地址不一致,生成的是可变副本,开辟了新的内存空间,是深拷贝。而NSMutableString的copy会开辟新的空间。

    本文代码

    ps:第一次写文章,想要改变一下自己,之前习惯做笔记,现在也要分享各位同学,这篇文章参考了好多的这位哥们的这篇博客,我写的有什么不对的地方希望大家多多指正!

    相关文章

      网友评论

          本文标题:Objective-C之原型模式

          本文链接:https://www.haomeiwen.com/subject/jgvswxtx.html