何為原型模式(Prototype)
****原型模式****: 在我看來就是克隆模式, 或者說是復(fù)制模式. 它是使用原型實例指定創(chuàng)建對象的種類, 并通過復(fù)制這個原型來創(chuàng)建新的對象.
****如下圖所示****:**

何時使用原型模式
- 類比較復(fù)雜, 創(chuàng)建對象比較麻煩, 采用原型設(shè)計模式, 從已有的對象復(fù)制會更加容易.
簡單的使用
定義一個協(xié)議 PrototypeCloneProtocol
#import <Foundation/Foundation.h>
@protocol PrototypeCloneProtocol <NSObject>
// 返回一個復(fù)制后的副本
- (id)clone;
@end
自定義一個Person類, 遵循PrototypeCloneProtocol協(xié)議.
****Person.h****
#import <Foundation/Foundation.h>
#import "PrototypeCloneProtocol.h"
@interface Person : NSObject<PrototypeCloneProtocol>
/** 姓名 */
@property (nonatomic, copy) NSString *name;
/** 年齡 */
@property (nonatomic, copy) NSString *age;
/** 性別 */
@property (nonatomic, copy) NSString *gender;
@end
****Person.m****
#import "Person.h"
@implementation Person
// 實現(xiàn)<PrototypeCloneProtocol>方法
- (id)clone {
Person *per = [[Person alloc] init];
per.name = self.name;
per.age = self.age;
per.gender = self.gender;
return per;
}
@end
****使用****
Person *per1 = [[Person alloc]init];
per1.name = @"張三";
per1.age = @"23";
per1.gender = @"男";
NSLog(@"%@ %@" ,per1, per1.name);
Person *per2 = [per1 clone];
NSLog(@"%@ %@", per2, per2.name);
****打印結(jié)果****
2016-11-27 21:03:38.119 Test[17799:1291137] per1: <Person: 0x7fd401759340> per1.name: 張三
2016-11-27 21:03:38.120 Test[17799:1291137] per2: <Person: 0x7fd4015153e0> per2.name: 張三
淺拷貝與深拷貝
說到復(fù)制, 就不得不說iOS中的深淺拷貝, 面試中經(jīng)常被問到.
****簡單的說****, 淺拷貝拷貝的是指向同一塊內(nèi)存的指針, 深拷貝拷貝的是內(nèi)容(內(nèi)存中不同位置的相同內(nèi)容);
****具體如圖所示****:
左側(cè)圖為淺拷貝, 右側(cè)為深拷貝.
當(dāng)進(jìn)行淺拷貝的時候, 系統(tǒng)向原始的集合發(fā)送retain的消息, 引用計數(shù)?****1****.
****對一個不可變數(shù)組進(jìn)行****copy****和****mutableCopy****操作****.
NSArray *array = [NSArray arrayWithObjects:@"張三", @"李四", @"王五", nil];
NSLog(@"%p", array);
NSLog(@"%p", [array copy]);
NSLog(@"%p", [array mutableCopy]);
****打印結(jié)果****
2016-11-27 21:50:48.871 Test[20474:1325670] 0x7fb7d6509a20
2016-11-27 21:50:48.872 Test[20474:1325670] 0x7fb7d6509a20
2016-11-27 21:50:48.872 Test[20474:1325670] 0x7fb7d674eb40
****對一個可變數(shù)組進(jìn)行****copy****和****mutableCopy****操作****
NSMutableArray *array = [NSMutableArray arrayWithCapacity:3];
NSLog(@"%p", array);
NSLog(@"%p", [array copy]);
NSLog(@"%p", [array mutableCopy]);
****打印結(jié)果****
2016-11-27 21:51:43.692 Test[20535:1326665] 0x7ff46fd21490
2016-11-27 21:51:43.694 Test[20535:1326665] 0x7ff46fe01b20
2016-11-27 21:51:43.694 Test[20535:1326665] 0x7ff46fe2c9f0
****對一個不可變字符串進(jìn)行****copy****和****mutableCopy****操作****
NSString *string = @"123";
NSLog(@"%p", string);
NSLog(@"%p", [string copy]);
NSLog(@"%p", [string mutableCopy]);
****打印結(jié)果****
2016-11-27 21:54:40.904 Test[20709:1328991] 0x101672098
2016-11-27 21:54:40.906 Test[20709:1328991] 0x101672098
2016-11-27 21:54:40.906 Test[20709:1328991] 0x7fa15dc78d20
****對可變字符串進(jìn)行****copy****和****mutableCopy****操作****
NSMutableString *string = [[NSMutableString alloc]init];
NSLog(@"%p", string);
NSLog(@"%p", [string copy]);
NSLog(@"%p", [string mutableCopy]);
****打印結(jié)果****
2016-11-27 21:59:59.458 Test[21073:1334395] 0x7fa524c1f120
2016-11-27 21:59:59.459 Test[21073:1334395] 0x109c43280
2016-11-27 21:59:59.459 Test[21073:1334395] 0x7fa524c467c0
****結(jié)論****:
對于一個不可變的對象進(jìn)行copy, 結(jié)果還是一個不可變的對象,地址不變,指針指向同一塊內(nèi)存空間是********淺拷貝********.
對于一個不可變的對象進(jìn)行mutableCopy, 生成一個可變的對象, 地址改變, 是********深拷貝********.
對一個可變對象不論copy還是mutableCopy, 地址都發(fā)生改變, 均為********深拷貝********.
****PS:****(以上僅為個人學(xué)習(xí), 如有誤區(qū), 請大神指正)