前言
本文csdn地址:http://blog.csdn.net/game3108/article/details/51154428
本文主要以代碼形式實現每一種設計模式,算是自己的一種復習和實踐。相應的代碼,也會放到github上。
本文的類圖均來自于《Objective-C編程之道 iOS設計模式解析》。
本篇主要講:
- 單例
- 原型
- 生成器
3.單例
概念:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
類圖:
Paste_Image.png
何時使用:
- 類只能有一個實例,而且必須從一個為人熟知的訪問點對其進行訪問。
- 這個唯一的實例只能通過子類化進行擴展,而且擴展的對象不會破壞客戶端代碼。
主要用了三種方式去實現:
1.dispatch_once方式
#import <Foundation/Foundation.h>
@interface SingletonGCDObject : NSObject
+ (instancetype) sharedInstance;
@end
#import "SingletonGCDObject.h"
@implementation SingletonGCDObject
+ (instancetype) sharedInstance{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
@end
2.synchronized方式
#import <Foundation/Foundation.h>
@interface SingletonSynObject : NSObject
+ (instancetype) sharedInstance;
@end
#import "SingletonSynObject.h"
static SingletonSynObject *singletonInstrance = nil;
@implementation SingletonSynObject
+ (instancetype) sharedInstance{
@synchronized (self) {
if ( singletonInstrance == nil )
singletonInstrance = [[SingletonSynObject alloc]init];
return singletonInstrance;
}
}
@end
3.initialize方式
#import <Foundation/Foundation.h>
@interface SingletonInitializeObject : NSObject
+ (instancetype) sharedInstance;
@end
#import "SingletonInitializeObject.h"
static SingletonInitializeObject *singletonInstrance = nil;
@implementation SingletonInitializeObject
+ (void)initialize{
singletonInstrance = [[SingletonInitializeObject alloc]init];
}
+ (instancetype) sharedInstance{
return singletonInstrance;
}
@end
4.原型
概念:使用原型實例指定創建對象的種類,并通過復制這個原型創建新的對象。
類圖:
Paste_Image.png
何時使用:
- 需要創建的對象應獨立于其類型與創建方式。
- 要實例化的類是在運行時決定的。
- 不想要與產品層次相對應的工廠層次。
- 不同類的實例間的差異僅是狀態的若干組合。因此復制相應數量的原型比手工實例化更加方便。
- 類不容易創建,比如每個組件可把其他組件作為子節點的組合對象。復制已有的組合對象并對副本進行修改會更加容易。
在Objective-C中,使用copy是最典型的原型的方式,而想使用copy方法,就要實現NSCopying的協議。具體代碼如下:
#import <Foundation/Foundation.h>
@interface PrototypeObject : NSObject<NSCopying>
@property (nonatomic, strong) NSString *property1;
@property (nonatomic, assign) NSInteger property2;
@property (nonatomic, copy) NSString *property3;
@end
#import "PrototypeObject.h"
@implementation PrototypeObject
- (id)copyWithZone:(nullable NSZone *)zone{
PrototypeObject *object = [[[self class] allocWithZone:zone] init];
object.property1 = self.property1;
object.property2 = self.property2;
object.property3 = [self.property3 copy];
return object;
}
@end
5.生成器
概念:將一個復雜對象的構建與它的表現分離,使得同樣的構建過程可以創建不同的表現。
類圖:
Paste_Image.png
何時使用:
- 需要創建涉及各種部件的復雜對象。創建對象的算法應該獨立于部件的裝配方式。
- 構建過程需要以不同的方式構建對象。
代碼場景:
一個新的主題樂園,需要指定一系列的活動計劃,包括活動第幾天,住在哪里,玩什么活動的門票等。
計劃類:
#import <Foundation/Foundation.h>
@interface Planner : NSObject
@property (nonatomic, assign) NSInteger date;
@property (nonatomic, copy) NSString *ticket;
@property (nonatomic, copy) NSString *hotel;
@end
計劃建造者的抽象:
#import <Foundation/Foundation.h>
#import "Planner.h"
@protocol AbstractBuilder <NSObject>
- (id<AbstractBuilder>) buildPlanner;
- (id<AbstractBuilder>) addDate:(NSInteger) date;
- (id<AbstractBuilder>) addHotel:(NSString *)hotel;
- (id<AbstractBuilder>) addTicket:(NSString *)ticket;
- (Planner *) getPlanner;
@end
計劃建造者的實現
#import <Foundation/Foundation.h>
#import "AbstractBuilder.h"
@interface VacationBuilder : NSObject<AbstractBuilder>
@end
#import "VacationBuilder.h"
@interface VacationBuilder(){
Planner *_planner;
}
@end
@implementation VacationBuilder
- (id<AbstractBuilder>) buildPlanner{
_planner = nil;
_planner = [[Planner alloc]init];
return self;
}
- (id<AbstractBuilder>) addDate:(NSInteger) date{
_planner.date = date;
return self;
}
- (id<AbstractBuilder>) addHotel:(NSString *)hotel{
_planner.hotel = hotel;
return self;
}
- (id<AbstractBuilder>) addTicket:(NSString *)ticket{
_planner.ticket = ticket;
return self;
}
- (Planner *) getPlanner{
return _planner;
}
@end
樂園類:
#import <Foundation/Foundation.h>
#import "Planner.h"
#import "AbstractBuilder.h"
@interface VacationPark : NSObject
- (Planner *)createFirstDayPlanner:(id<AbstractBuilder>)builder;
- (Planner *)createSecondDayPlanner:(id<AbstractBuilder>)builder;
@end
#import "VacationPark.h"
#import "VacationBuilder.h"
@implementation VacationPark
- (Planner *)createFirstDayPlanner:(id<AbstractBuilder>)builder{
[builder buildPlanner];
[builder addDate:1];
[builder addHotel:@"如家"];
[builder addTicket:@"過山車"];
return [builder getPlanner];
}
- (Planner *)createSecondDayPlanner:(id<AbstractBuilder>)builder{
[builder buildPlanner];
[builder addDate:2];
[builder addHotel:@"漢庭"];
[builder addTicket:@"鬼屋"];
return [builder getPlanner];
}
@end
總結:
1.應該盡量少的使用單例,因為單例的生命周期控制會比較麻煩。尤其是當添加了撤銷單例以后。參考鏈接Avoiding Singleton Abuse(譯文:避免濫用單例)。
2.生成器與抽象工廠的對比:
生成器:
- 構建復雜對象
- 以多個步驟構建對象
- 以多種方式構建對象
- 在構建過程的最后一步返回產品
- 專注一個特定產品
抽象工廠:
- 構建簡單或復雜對象
- 以單一步驟構建對象
- 以單一方式構建對象
- 立即返回產品
- 強調一套產品
參考資料
1.《Objective-C編程之道 iOS設計模式解析》
2.《Head First設計模式》