原型模式的解析-iOS
其他设计模式的介绍
1、简单工厂模式、工厂模式、抽象工厂模式的解析-iOS
2、建造者模式的解析-iOS
3、单例模式的解析-iOS
4、原型模式的解析-iOS
概率描述
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。百度百科
实用场景
“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。百度百科
在Objective-C中使用原型模式
在Objective-C中使用原型模式,就是说对对象的复制,就是我们常说的深拷贝和浅拷贝。在Cocoa Touch框架为NSObject的派生类提供了实现深拷贝的协议和相应的方法,NSCopying协议和-(id)copyWithZone:(NSZone )zone的方法。还有就是NSMutableCopying 和-(id)mutableCopyWithZone:(NSZone )zone的协议和方式。
也就是说如果要实现拷贝,就需要实现NSCopying协议和-(id)copyWithZone:(NSZone )zone的方法。如果是可变的要实现NSMutableCopying协议和-(id)copyWithZone:(NSZone )zone方法。
深拷贝、浅拷贝
浅拷贝:只是复制了指针的地址,并没有复制该指针指向的地址。
深拷贝:不但复制了指针的地址,还复制了指针地址指向的值。
代码解析:
-(void)shallowAndDeepCopy{
/*******集合类的**********/
//非可变集合
NSDictionary *prototypeDic = @{@"A":@"1",@"B":@"2",@"C":@"3",@"D":@"4"};
NSDictionary *copyDicOne = prototypeDic.copy;
NSDictionary *copyDicTwo = prototypeDic.mutableCopy;
NSLog(@"集合类的拷贝------------\n prototypeDic的内容地址-%p \n copyDicOne-copy-的内容地址-%p \n copyDicTwo-Mutable-的内容地址-%p \n",prototypeDic,copyDicOne,copyDicTwo);
NSLog(@"集合类的拷贝------------\n prototypeDic的指针地址-%p \n copyDicOne-copy-的指针地址-%p \n copyDicTwo-Mutable-的指针地址-%p \n",&prototypeDic,©DicOne,©DicTwo);
//可变集合
NSMutableDictionary *prototypeMutableDic =[[NSMutableDictionary alloc]initWithObjectsAndKeys:@"A",@"1",@"B",@"2",@"C",@"3",@"D",@"4", nil ];
NSMutableDictionary *copyMutaleDicOne = prototypeMutableDic.copy;
NSMutableDictionary *copyMutaleDicTwo = prototypeMutableDic.mutableCopy;
NSLog(@"可变集合类的拷贝------------\n prototypeMutableDic的内容地址-%p \n copyMutaleDicOne-copy-的内容地址-%p \n copyMutaleDicTwo-Mutable-的内容地址-%p \n",prototypeMutableDic,copyMutaleDicOne,copyMutaleDicTwo);
NSLog(@"可变集合类的拷贝------------\n prototypeMutableDic的指针地址-%p \n copyMutaleDicOne-copy-的指针地址-%p \n copyMutaleDicTwo-Mutable-的指针地址-%p \n",&prototypeMutableDic,©MutaleDicOne,©MutaleDicTwo);
/**********非集合类的**********/
//不可变的
NSString *prototypeStr = @"猪猪侠";
NSString *copyStrOne = prototypeStr.copy;
NSString *copyStrTwo = prototypeStr.mutableCopy;
NSLog(@"非集合类的拷贝------------\n prototypeStr的内容地址-%p \n copyStrOne-copy-的内容地址-%p \n copyStrTwo-Mutable-的内容地址-%p \n",prototypeStr,copyStrOne,copyStrTwo);
NSLog(@"非集合类的拷贝------------\n prototypeStr的指针地址-%p \n copyStrOne-copy-的指针地址-%p \n copyStrTwo-Mutable-的指针地址-%p \n",&prototypeStr,©StrOne,©StrTwo);
//可变的
NSMutableString *prototypeMutableStr = [[NSMutableString alloc]initWithString:@"小猪佩奇"];
NSMutableString *copyMutabelStrOne = prototypeMutableStr.copy;
NSMutableString *copyMutabelStrTwo = prototypeMutableStr.mutableCopy;
NSLog(@"可变非集合类的拷贝------------\n prototypeMutableStr的内容地址-%p \n copyMutabelStrOne-copy-的内容地址-%p \n copyMutabelStrTwo-Mutable-的内容地址-%p \n",prototypeMutableStr,copyMutabelStrOne,copyMutabelStrTwo);
NSLog(@"可变非集合类的拷贝------------\n prototypeMutableStr的指针地址-%p \n copyMutabelStrOne-copy-的指针地址-%p \n copyMutabelStrTwo-Mutable-的指针地址-%p \n",&prototypeMutableStr,©MutabelStrOne,©MutabelStrTwo);
}
打印的结果
2018-06-12 15:04:35.457387+0800 DesignDemo[17492:692166] 集合类的拷贝------------
prototypeDic的内容地址-0x6000000f2100
copyDicOne-copy-的内容地址-0x6000000f2100
copyDicTwo-Mutable-的内容地址-0x60000023e540
2018-06-12 15:04:35.457509+0800 DesignDemo[17492:692166] 集合类的拷贝------------
prototypeDic的指针地址-0x7ffeecd84988
copyDicOne-copy-的指针地址-0x7ffeecd84980
copyDicTwo-Mutable-的指针地址-0x7ffeecd84978
2018-06-12 15:04:35.457617+0800 DesignDemo[17492:692166] 可变集合类的拷贝------------
prototypeMutableDic的内容地址-0x60000023ce40
copyMutaleDicOne-copy-的内容地址-0x60000023d2c0
copyMutaleDicTwo-Mutable-的内容地址-0x600000420160
2018-06-12 15:04:35.457896+0800 DesignDemo[17492:692166] 可变集合类的拷贝------------
prototypeMutableDic的指针地址-0x7ffeecd84970
copyMutaleDicOne-copy-的指针地址-0x7ffeecd84968
copyMutaleDicTwo-Mutable-的指针地址-0x7ffeecd84960
2018-06-12 15:04:35.458083+0800 DesignDemo[17492:692166] 非集合类的拷贝------------
prototypeStr的内容地址-0x102e7c4d8
copyStrOne-copy-的内容地址-0x102e7c4d8
copyStrTwo-Mutable-的内容地址-0x604000442580
2018-06-12 15:04:35.458478+0800 DesignDemo[17492:692166] 非集合类的拷贝------------
prototypeStr的指针地址-0x7ffeecd84958
copyStrOne-copy-的指针地址-0x7ffeecd84950
copyStrTwo-Mutable-的指针地址-0x7ffeecd84948
2018-06-12 15:04:35.458711+0800 DesignDemo[17492:692166] 可变非集合类的拷贝------------
prototypeMutableStr的内容地址-0x600000257df0
copyMutabelStrOne-copy-的内容地址-0x60000023d440
copyMutabelStrTwo-Mutable-的内容地址-0x600000257c10
2018-06-12 15:04:35.459056+0800 DesignDemo[17492:692166] 可变非集合类的拷贝------------
prototypeMutableStr的指针地址-0x7ffeecd84940
copyMutabelStrOne-copy-的指针地址-0x7ffeecd84938
copyMutabelStrTwo-Mutable-的指针地址-0x7ffeecd84930
从上面的结果我们可以知道:
1、非集合类
不可变非集合类的对象copy: 指针拷贝,共同内存
不可变的非集合类的对象mutableCopy:是对内容的的拷贝,创建了新的内存空间。
可变的非集合类的对象copy:是对内容的拷贝,创建的新的内存空间
可变的非集合类的对象mutableCopy:是对内容的拷贝,创建的新的内存空间
2、集合类的
不可变集合类的对象copy: 指针拷贝,共同内存
不可变的集合类的对象mutableCopy:是对内容的的拷贝,创建了新的内存空间。
可变的集合类的对象copy:是对内容的拷贝,创建的新的内存空间
可变的集合类的对象mutableCopy:是对内容的拷贝,创建的新的内存空间
案例解析
我们先来分析一下,比如:小明喜欢看书,就买了一本《小王子》的书。
代码如下:
人物类的代码
#import "PrototypePerson.h"
@interface PrototypePerson ()
@property(nonatomic,strong)NSMutableArray *bookArray;
@property(nonatomic,copy)NSString *name;
/*
*init方法
*/
- (instancetype)initWithName:(NSString *)name;
/*
*添加书
*/
-(void)addBook:(NSString *)bookName;
@end
@implementation PrototypePerson
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
_name = name;
_bookArray = [[NSMutableArray alloc] initWithCapacity:20];
}
return self;
}
-(void)addBook:(NSString *)bookName{
[_bookArray addObject:bookName];
}
@end
小明买书的代码
//原型模式
//平常模式
PrototypePerson *prototypePersonOne = [[PrototypePerson alloc]initWithName:@"小明"];
//小明买了本《小王子》的书
[prototypePersonOne addBook:@"《小王子》"];
//现在小黄,也买了一个书柜,也买了本《小王子》的书
PrototypePerson *prototypePersonTwo = [[PrototypePerson alloc]initWithName:@"小黄"];
[prototypePersonTwo addBook:@"《小王子》"];
然后小黄发现小明这本书很好,他就买了一本一摸一样的书。
代码如下
PrototypePerson *prototypePersonOne = [[PrototypePerson alloc]initWithName:@"小明"];
//小明买了本《小王子》的书
[prototypePersonOne addBook:@"《小王子》"];
//现在小黄,也买了一个书柜,也买了本《小王子》的书
PrototypePerson *prototypePersonTwo = [[PrototypePerson alloc]initWithName:@"小黄"];
[prototypePersonTwo addBook:@"《小王子》"];
现在小明只有一本书,我们就只要添加一本书就行,如果过段时间小明有几百本书,这个时候小黄根据小明的书籍买了一摸一样的书籍,这个时候,我们还需要一本一本的书籍添加吗?
这个时候原型模式就派上用场了。我们可以在我们人物类上面实现NSCopying协议,实现- (id)copyWithZone:(NSZone *)zone方法,这样就实现了小明这个人物的深拷贝。
代码如下:
人物类的代码:
#import "PrototypePerson.h"
@interface PrototypePerson ()<NSCopying>
@property(nonatomic,strong)NSMutableArray *bookArray;
@property(nonatomic,copy)NSString *name;
/*
*init方法
*/
- (instancetype)initWithName:(NSString *)name;
/*
*添加书
*/
-(void)addBook:(NSString *)bookName;
@end
@implementation PrototypePerson
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
_name = name;
_bookArray = [[NSMutableArray alloc] initWithCapacity:20];
}
return self;
}
-(void)addBook:(NSString *)bookName{
[_bookArray addObject:bookName];
}
-(id)copyWithZone:(NSZone *)zone{
PrototypePerson *prototypePerson = [[[self class] allocWithZone:zone]initWithName:_name];
prototypePerson.bookArray = [_bookArray mutableCopy];
return prototypePerson;
}
@end
//对小明人物类的深拷贝
//原型模式
PrototypePerson *prototypePersonOne = [[PrototypePerson alloc]initWithName:@"小明"];
//小明买了本《小王子》的书
[prototypePersonOne addBook:@"《小王子》"];
//如果,以后小明买了很多本书,过了一段时间,小黄,和他买了一摸一样的书籍,这个时候就可以使用原型模式,实现NSCopying协议,实现- (id)copyWithZone:(NSZone *)zone方法来实现对象的拷贝。
//小黄
PrototypePerson *prototypePersonThree =[prototypePersonOne copy];
//小黄发现了一本很好的书
[prototypePersonThree addBook:@"《睡前故事》"];
NSLog(@"小明内存地址 ---- %p \n 小黄内存地址 -----%p",prototypePersonOne,prototypePersonThree);
我们来打印一下,小明和小黄的内存地址和购买的书籍数据
2018-06-12 16:36:49.541459+0800 DesignDemo[19613:790893] 小明内存地址 ---- 0x600000237700
小黄内存地址 -----0x6000002373e0
2018-06-12 16:36:49.541741+0800 DesignDemo[19613:790893] 小明的书籍 ---- (
"\U300a\U5c0f\U738b\U5b50\U300b"
)
小黄内存书籍 -----(
"\U300a\U5c0f\U738b\U5b50\U300b",
"\U300a\U7761\U524d\U6545\U4e8b\U300b"
)
根据上面的结果,我们发现小明和小黄的内存地址不一样,说明实现了深拷贝,小明和小黄豆是购买了《小王子》这本书籍,小黄还买了本《睡前故事》。
总结
如果有写的不正确或者侵权的,希望大家给我提出来,我会及时修改。谢谢大家。