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

相关文章

  • 原型模式

    WHAT原型模式: 原型模式在Objective-C中,最直观的表现就是NSObject的- (id)copy;方...

  • Objective-C之原型模式

    原型模式 原型模式是非常简单的一种模式,在我们的实际开发中经常用到这种模式,例如你创建的可变字典、可变字符串调用c...

  • iOS 原型模式

    原型模式是非常简单的一种设计模式, 在多数情况下可被理解为一种深复制的行为。在Objective-C中使用原型模式...

  • 设计模式之原型模式

    设计模式之原型模式 Intro 简介 原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 原...

  • 创建型模式:原型模式

    个人公众号原文:创建型模式:原型模式 五大创建型模式之五:原型模式。 简介 姓名 :原型模式 英文名 :Proto...

  • 设计模式之原型模式

    设计模式之原型模式 原型模式 属于 创建型模式,提供创建对象的最佳方式。 原型模式 简介 也就是 说 根据一个已有...

  • iOS模式设计之--创建型:5、原型模式(Prototype)

    iOS模式设计之--5、原型模式(Prototype)

  • 原型模式

    Android进阶之设计模式 原型模式 定义: 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 使...

  • Android设计模式源码解析之原型模式

    Android设计模式源码解析之原型模式 【备注】只用于个人收藏

  • 设计模式三十六计之原型模式(Prototype)

    设计模式三十六计之原型模式(Prototype) 1. 设计思想 将一个对象作为指定的原型实例,并通过克隆此原型来...

网友评论

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

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