原型模式
原型模式(Prototype Pattern)是用于創(chuàng)建重復(fù)的對象遗嗽,同時又能保證性能踩蔚。這種類型的設(shè)計模式屬于創(chuàng)建型模式搬俊,它提供了一種創(chuàng)建對象的最佳方式。
這種模式是實現(xiàn)了一個原型接口睛榄,該接口用于創(chuàng)建當前對象的克隆。當直接創(chuàng)建對象的代價比較大時想帅,則采用這種模式。例如博脑,一個對象需要在一個高代價的數(shù)據(jù)庫操作之后被創(chuàng)建。我們可以緩存該對象叉趣,在下一個請求時返回它的克隆,在需要的時候更新數(shù)據(jù)庫疗杉,以此來減少數(shù)據(jù)庫調(diào)用。
介紹
意圖:用原型實例指定創(chuàng)建對象的種類烟具,并且通過拷貝這些原型創(chuàng)建新的對象梢什。
主要解決:在運行期建立和刪除原型朝聋。
何時使用: 1、當一個系統(tǒng)應(yīng)該獨立于它的產(chǎn)品創(chuàng)建冀痕,構(gòu)成和表示時。 2言蛇、當要實例化的類是在運行時刻指定時,例如腊尚,通過動態(tài)裝載。 3婿斥、為了避免創(chuàng)建一個與產(chǎn)品類層次平行的工廠類層次時。 4受扳、當一個類的實例只能有幾個不同狀態(tài)組合中的一種時携龟。建立相應(yīng)數(shù)目的原型并克隆它們可能比每次用合適的狀態(tài)手工實例化該類更方便一些兔跌。
如何解決:利用已有的一個原型對象勘高,快速地生成和原型對象一樣的實例。
關(guān)鍵代碼: 1、實現(xiàn)克隆操作华望,在 JAVA 繼承 Cloneable蕊蝗,重寫 clone(),在 .NET 中可以使用 Object 類的 MemberwiseClone() 方法來實現(xiàn)對象的淺拷貝或通過序列化的方式來實現(xiàn)深拷貝赖舟。 2蓬戚、原型模式同樣用于隔離類對象的使用者和具體類型(易變類)之間的耦合關(guān)系,它同樣要求這些"易變類"擁有穩(wěn)定的接口宾抓。
應(yīng)用實例: 1子漩、細胞分裂。 2石洗、JAVA 中的 Object clone() 方法幢泼。
優(yōu)點: 1、性能提高讲衫。 2缕棵、逃避構(gòu)造函數(shù)的約束。
缺點: 1涉兽、配備克隆方法需要對類的功能進行通盤考慮招驴,這對于全新的類不是很難,但對于已有的類不一定很容易枷畏,特別當一個類引用不支持串行化的間接對象别厘,或者引用含有循環(huán)結(jié)構(gòu)的時候。 2拥诡、必須實現(xiàn) Cloneable 接口丹允。
使用場景: 1、資源優(yōu)化場景袋倔。 2雕蔽、類初始化需要消化非常多的資源,這個資源包括數(shù)據(jù)宾娜、硬件資源等批狐。 3、性能和安全要求的場景前塔。 4嚣艇、通過 new 產(chǎn)生一個對象需要非常繁瑣的數(shù)據(jù)準備或訪問權(quán)限,則可以使用原型模式华弓。 5食零、一個對象多個修改者的場景。 6寂屏、一個對象需要提供給其他對象訪問贰谣,而且各個調(diào)用者可能都需要修改其值時娜搂,可以考慮使用原型模式拷貝多個對象供調(diào)用者使用。 7吱抚、在實際項目中,原型模式很少單獨出現(xiàn)秘豹,一般是和工廠方法模式一起出現(xiàn)既绕,通過 clone 的方法創(chuàng)建一個對象,然后由工廠方法提供給調(diào)用者鸵膏。原型模式已經(jīng)與 Java 融為渾然一體谭企,大家可以隨手拿來使用评肆。
注意事項:與通過對一個類進行實例化來構(gòu)造新對象不同的是,原型模式是通過拷貝一個現(xiàn)有對象生成新對象的盹廷。淺拷貝實現(xiàn) Cloneable俄占,重寫淆衷,深拷貝是通過實現(xiàn) Serializable 讀取二進制流。
實現(xiàn)
我們將創(chuàng)建一個抽象類 Shape 和擴展了 Shape 類的實體類甚带。下一步是定義類 ShapeCache鹰贵,該類把 shape 對象存儲在一個 Hashtable 中康嘉,并在請求的時候返回它們的克隆亭珍。
PrototypePatternDemo枝哄,我們的演示類使用 ShapeCache 類來獲取 Shape 對象膘格。
步驟 1
創(chuàng)建一個實現(xiàn)了 Cloneable 接口的抽象類财松。
@interface ShapeCopy : NSObject
@property (nonatomic,copy) NSString * name;
@property (nonatomic,assign) int age;
- (void)draw;
@end
@implementation ShapeCopy
- (instancetype)copy
{//實現(xiàn)深拷貝
ShapeCopy *c =[[ShapeCopy alloc]init];
c.name = self.name;
c.age = self.age;
return c;
}
@end
步驟 2
創(chuàng)建擴展了上面抽象類的實體類辆毡。
@interface RectangleCopy : ShapeCopy
@end
@interface SquareCopy : ShapeCopy
@end
@implementation RectangleCopy
- (instancetype)copy
{
RectangleCopy *c =[[RectangleCopy alloc]init];
c.name = self.name;
c.age = self.age;
return c;
}
-(NSString *)name{
return @"RectangleCopy";
}
- (void)draw{
NSLog(@"inside RectangleCopy draw method");
}
@end
@implementation SquareCopy
- (instancetype)copy
{
SquareCopy *c =[[SquareCopy alloc]init];
c.name = self.name;
c.age = self.age;
return c;
}
-(NSString *)name{
return @"SquareCopy";
}
- (void)draw{
NSLog(@"inside SquareCopy draw method");
}
@end
步驟 3
創(chuàng)建一個類舶掖,從數(shù)據(jù)庫獲取實體類眨攘,并把它們存儲在一個 Hashtable 中鲫售。
@interface ShapeCache : NSObject
@property (nonatomic,strong) NSMutableDictionary *dic;
- (void)loadCache;
- (ShapeCopy *)getShape:(NSString *)name;
@end
@implementation ShapeCache
- (NSMutableDictionary *)dic{
if (_dic == nil) {
_dic =[NSMutableDictionary dictionary];
}
return _dic;
}
- (void)loadCache{
SquareCopy *sq=[SquareCopy new];
[self.dic setObject:sq forKey:@"1"];
RectangleCopy *re =[RectangleCopy new];
[self.dic setObject:re forKey:@"2"];
}
- (ShapeCopy *)getShape:(NSString *)name{
if ([self.dic.allKeys containsObject:name]) {
return [[self.dic objectForKey:name] copy];
}
return nil;
}
@end
步驟 4
PrototypePatternDemo 使用 ShapeCache 類來獲取存儲在 Hashtable 中的形狀的克隆情竹。
ShapeCache *cahce=[ShapeCache new];
[cahce loadCache];
ShapeCopy *sp1 =[cahce getShape:@"1"];
NSLog(@"name:%@",sp1.name);
ShapeCopy *sp2 =[cahce getShape:@"2"];
NSLog(@"name:%@",sp2.name);
步驟 5
執(zhí)行程序匀哄,輸出結(jié)果:
2019-05-20 17:23:08.361458+0800 test[11713:17803701] name:SquareCopy
2019-05-20 17:23:08.361575+0800 test[11713:17803701] name:RectangleCopy
參考資料
runoob