1. 什么是原型模式
原型模式(Prototype Pattern) 定義
Specify the kinds of objects to create using a prototypical instance,and create new objects by copying thisprototype.(用原型實(shí)例指定創(chuàng)建對(duì)象的種類昭伸,并且通過拷貝這些原型創(chuàng)建新的對(duì)象烟具。)
是用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型靶端,通過復(fù)制該原型對(duì)象來創(chuàng)建一個(gè)和原型相同或相似的新對(duì)象融痛。
Object-C中提供了對(duì)象的copy和mutableCopy方法,只需要實(shí)力類實(shí)現(xiàn)NSCopying和NSMutableCopying協(xié)議即可實(shí)現(xiàn)復(fù)制
2. 角色組成
原型模式包含以下主要角色:
- 抽象原型類(Prototype):規(guī)定了具體原型對(duì)象支持復(fù)制必須實(shí)現(xiàn)的接口(在Object-C中指的是NSCopying或NSMutableCopying協(xié)議)
- 具體原型類(ConcretePrototype):實(shí)現(xiàn)抽象原型類的支持復(fù)制必須實(shí)現(xiàn)的接口(在Object-C中指的是實(shí)現(xiàn) - (id)copyWithZone:(nullable NSZone *)zone 或 - (id)mutableCopyWithZone:(nullable NSZone *)zone 方法)
- 訪問類(Client):使用具體原型類中的復(fù)制方法來復(fù)制新的對(duì)象狮腿。(在Object-C中指的是copy或者mutableCopy )
原型模式
3. 代碼實(shí)現(xiàn)
我們以畫圓(Circle)為例腿宰,假設(shè)我們需要在一張圖畫三個(gè)一模一樣的圖,除了圓心位置不同缘厢。
- 抽象原型類我們不用自己建立了吃度,在Object-C中已經(jīng)有了,我們選取 NSCopying協(xié)議作為原型模式的抽象原型類
- 創(chuàng)建和定義具體原型類 Circle, 并實(shí)現(xiàn)NSCopyong協(xié)議
//Circle
#import <Foundation/Foundation.h>
@interface Circle : NSObject<NSCopying>
@property (nonatomic, assign) CGFloat radius;
@property (nonatomic, assign) CGFloat lineWidth;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
@end
// Circle.m
#import "Circle.h"
@implementation Circle
- (id)copyWithZone:(NSZone *)zone {
Circle *ret = [[self class] allocWithZone:zone];
ret.radius = self.radius;
ret.lineWidth = self.lineWidth;
ret.centerX = self.centerX;
ret.centerY = self.centerY;
return ret;
}
- (NSString *)description {
return [NSString stringWithFormat:@"address = %p, radius = %lf, lineWidth = %lf, centerX = %lf, centerY = %lf", self, self.radius, self.lineWidth, self.centerX, self.centerY];
}
@end
- 調(diào)用測試
+ (void)test {
Circle *c1 = [[Circle alloc] init];
c1.radius = 10.f;
c1.lineWidth = 5.f;
c1.centerX = 10.f;
c1.centerY = 10.f;
NSLog(@"c1: %@",c1);
Circle *c2 = [c1 copy];
c2.centerX = 40.f;
c2.centerY = 40.f;
NSLog(@"c2: %@",c2);
Circle *c3 = [c1 copy];
c3.centerX = 60.f;
c3.centerY = 60.f;
NSLog(@"c3: %@",c3);
}
可以看到每個(gè)Circle實(shí)例贴硫,地址是不同的椿每,且內(nèi)容里面除了位置信息,其他信息都是相同的
運(yùn)行結(jié)果
4. 分析
- 復(fù)制的過程封閉到被復(fù)制對(duì)象的內(nèi)部完成夜畴,修改復(fù)制的過程而不影響外部的使用者拖刃,滿足迪米特原則。
- 對(duì)于只有部分屬性變化的實(shí)例贪绘,不需要重新去創(chuàng)建進(jìn)行并對(duì)每個(gè)屬性進(jìn)行重新賦值兑牡。
- 但是子類進(jìn)行拓展屬性時(shí),需要重新實(shí)現(xiàn)復(fù)制相關(guān)協(xié)議接口税灌,否則會(huì)出現(xiàn)復(fù)制不完全的問題
- 克隆包含循環(huán)引用的復(fù)雜對(duì)象可能會(huì)非常麻煩
5. 適用場景
- 對(duì)象之間相同或相似均函,即只是個(gè)別的幾個(gè)屬性不同的時(shí)候。
- 對(duì)象的創(chuàng)建過程比較麻煩菱涤,但復(fù)制比較簡單的時(shí)候苞也。
- 在實(shí)際項(xiàng)目中,可以和工廠方法模式一起出現(xiàn)粘秆,通過copy的方法創(chuàng)建一個(gè)對(duì)象如迟,然后由工廠方法提供給調(diào)用者