何為原型模式撞牢?
原型模式:例如客戶端知道抽象Prototype類摆马,在運(yùn)行時(shí)性穿,抽象Prototype子類的任何對(duì)象都可以按客戶端的意愿被復(fù)制。因此愕鼓,無需手工創(chuàng)建就可以制造同一類型的多個(gè)實(shí)例钙态。可以簡單理解為創(chuàng)建第一個(gè)模版對(duì)象菇晃,然后通過復(fù)制(深拷貝)模版來創(chuàng)建新的對(duì)象册倒。
從功能的角度看,不管什么對(duì)象磺送,只要復(fù)制自身比手工實(shí)例化要好驻子,都可以是原型對(duì)象。
何時(shí)使用原型模式估灿?
1.需要?jiǎng)?chuàng)建的對(duì)象應(yīng)獨(dú)立于其類型與創(chuàng)建方式崇呵。是說想要?jiǎng)?chuàng)建的對(duì)象不能直接通過初始化函數(shù)來創(chuàng)建,創(chuàng)建方式不具有普遍性馅袁,比較復(fù)雜域慷。
2.要實(shí)例化的類是在運(yùn)行時(shí)決定的。是說在編寫代碼時(shí)汗销,并不知道哪種對(duì)象會(huì)被創(chuàng)建犹褒,取決于用戶的操作,且內(nèi)部結(jié)構(gòu)復(fù)雜弛针。
3.不想要與產(chǎn)品層次相對(duì)應(yīng)的工廠層次叠骑。是說不通過工廠方法或抽象工廠來控制產(chǎn)品的創(chuàng)建過程。
4.不用類的實(shí)例間的差異僅是狀態(tài)的若干組合削茁。因此復(fù)制相應(yīng)數(shù)量的原型比手工實(shí)例化更加方便宙枷。
5.類不容易創(chuàng)建,比如每個(gè)組件可把其他組件作為子節(jié)點(diǎn)的組合對(duì)象付材。復(fù)制已有的組合對(duì)象并對(duì)副本進(jìn)行修改會(huì)更加容易朦拖。
兩種特別常見的情形:
1.有很多相關(guān)的類,其行為略有不同厌衔,,而且主要差異在于內(nèi)部屬性捍岳,如名稱富寿、圖像睬隶。
2.需要使用組合(樹型)對(duì)象作為其他東西的基礎(chǔ),例如页徐,使用組合對(duì)象作為組建來構(gòu)建另一個(gè)組件對(duì)象苏潜。
原理UML圖
簡單使用
定義協(xié)議
#import <Foundation/Foundation.h>
@protocol PrototypeProtocol <NSObject>
- (id)copy;
@end
Prototype子類
//.h
#import <Foundation/Foundation.h>
#import "PrototypeProtocol.h"
@interface Prototype : NSObject<PrototypeProtocol,NSCopying>
@property (nonatomic, copy) NSString * name;
@end
//.m
#import "Prototype.h"
@implementation Prototype
- (id)copyWithZone:(NSZone *)zone{
Prototype * prototype = [[self class] allocWithZone:zone];
prototype.name = self.name;
return prototype;
}
@end
Prototype子類遵守協(xié)議。
并一起遵守NSCopying協(xié)議变勇,然后重寫-(id)copyWithZone:(NSZone *)zone方法恤左。
而且通過上述代碼可以發(fā)現(xiàn),我們并沒有用copy方法搀绣,而是用copyWithZone:方法飞袋,這是因?yàn)镹SObject協(xié)議沒有聲明copy方法,但是NSObject聲明了NSObject型的接收器收到copy消息時(shí)链患,NSObject會(huì)依次向其采用了NSCopying協(xié)議的子類轉(zhuǎn)發(fā)消息巧鸭。子類要實(shí)現(xiàn)所需的NSCopying中定義的copyWithZone:方法,以返回自身的副本麻捻。如果子類沒有實(shí)現(xiàn)此方法纲仍,會(huì)拋出NSInvalidArgumentException的實(shí)例。這就是為什么要讓Prototype類采用NSCopying協(xié)議并為復(fù)制處理實(shí)現(xiàn)其copyWithZone:方法贸毕。而NSObject協(xié)議沒有聲明copy方法郑叠,所以在PrototypeProtocol協(xié)議聲明它,以避免編譯警告明棍。
在重寫時(shí)乡革,使用了[self class]是因?yàn)橄M渥宇愐材軌驈?fù)用這個(gè)復(fù)制方法。
//ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Prototype * p = [[Prototype alloc] init];
p.name = @"John";
Prototype * p1 = [p copy];
p1.name = @"Bob";
NSLog(@"p.name == %@----p1.name == %@",p.name,p1.name);
}
//p.name == John----p1.name == Bob
雖然使用的例子比較簡單击蹲,但是便于理解署拟,假如類的內(nèi)部屬性較多,實(shí)例化比較復(fù)雜歌豺,原型模式將會(huì)是非常簡單的創(chuàng)建模式推穷。