目錄
- 官方用到的幾種設計模式
- 代理模式(Proxy)
- 觀察者模式(Observer)
- 單例模式(Singleton)
- 工廠模式(Factory)
- 策略模式(Strategy)
- 裝飾模式(Decorator)
- 適配器模式(Adapter)
- MVC及一些衍生設計模式
官方用到的幾種設計模式
官方的用法總是我們很關心、也是值得學習的
代理模式(Proxy Pattern)
當一個類的某些功能需要由別的類來實現、但是又不確定具體會是哪個類實現。
有兩個主體:委託者(方法調用者
)、代理者(方法實現者
)。
Cocoa下的應用:
UITableView、UIAlertView、NSURLSession等等
觀察者模式(Observer)
主要負責對象間的通訊。
觀察者註冊自己感興趣的事件、被觀察者不需要知道觀察者的存在。
-
通知
Cocoa下的應用:
鍵盤升降(UIKeyboardWillShowNotification
、UIKeyboardWillHideNotification
)、前後臺切換(name:UIApplicationDidEnterBackgroundNotification
、UIApplicationDidBecomeActiveNotification
)等等
-
KVO
具體應用:下載進度條、表單填寫狀態的更新。
不過實際上cocoa並沒有給我們暴露直接使用KVO的例子。
單例模式(Singleton)
主要用於共享資源、並且確保該實例只被初始化一次。
Cocoa下的應用:
[NSUserDefaults standardUserDefaults]
、 [UIApplication sharedApplication]
、[UIScreen mainScreen]
、[NSFileManager defaultManager]
等等。
工廠模式
專門定義一個類來負責創建其他類的實例、被創建的實例常常具有共同的父類(基於多態)。
工廠模式分爲三種:簡單工廠模式、工廠模式、抽象工廠模式。
-
簡單工廠模式
由一個工廠類、根據傳入的參數(
通常是枚舉
)、動態的決定創建出哪一個產品類的實例。
適用於負責創建的對象比較少的情況下使用、簡單工廠的穩定性和可擴展性會隨着數量的增加而下降。
需要以下三個元素:
1. 工廠(Factory)
角色接受客戶端的請求、通過請求負責創建相應的產品對象。
2. 抽象產品(Abstract Product)
工廠模式所創建對象的父類或是共同擁有的接口、可是抽象類或接口<也就是協議
>。
3. 具體產品(ConcreteProduct)
工廠模式所創建的對象都是這個產品實例。
工廠實現:
//AnimalHouse
+ (Animal *)animalWithType:(AnimalType)type {
Animal *animal = nil;
if (type == AnimalTypeDog) {//狗
animal = [[Dog alloc] init];
} else if (type == AnimalTypeCat) {
animal = [[Cat alloc] init];
} else if (type == AnimalTypeSheep) {
animal = [[Sheep alloc] init];
}
return animal;
}
使用起來:
Animal *dog = [AnimalHouse animalWithType:AnimalTypeDog];
[dog shout];
Animal *cat = [AnimalHouse animalWithType:AnimalTypeCat];
[cat shout];
Animal *sheep = [AnimalHouse animalWithType:AnimalTypeSheep];
[sheep shout];
需要注意的是、如果只是將參數賦值給產品(比如顏色等等
)、是並不能算作簡單工廠模式的。
-
工廠模式(Factory)
相比簡單工廠、將《工廠》也進行抽象處理。
解決了簡單工廠模式下、臃腫的工廠導致增加產品時不宜擴展的弊端。
需要以下四個角色:
1. 抽象工廠
與業務方無關、任何在模式中創建對象的工廠必須實現這個接口。
2. 具體工廠
實現了抽象工廠接口的具體類、含有與引用密切相關的邏輯、並且受到業務方的調用以創建產品對象。
3. 抽象產品
工廠方法所創建產品對象的超類型,也就是產品對象的共同父類或共同擁有的接口。
4.具體產品
這個角色實現了抽象產品角色所聲名的接口。工廠方法所創建的每個具體產品對象都是某個具體產品角色的實例。
以其中一個工廠爲例:
與抽象工廠AnimalHouse
(動物之家)相比、具體工廠DogHouse
(狗窩)隸屬於動物園。狗窩裏自然全是狗~
//DogHouse
+ (Animal *)animal {
Animal *animal = [[Dog alloc] init];
return animal;
}
使用起來:
Animal *dog = [DogHouse animal];
[dog shout];
Animal *cat = [CatHouse animal];
[cat shout];
Animal *sheep = [SheepHouse animal];
[sheep shout];
雖然解決了擴展性。但依舊有個問題、就是當工廠太多、業務需要使用的工廠類型也太多了~
-
抽象工廠模式
與工廠模式的基本模式相同。最大的區別就是工廠實例不在只生產一種產品、而是生產一個產品族。
抽象工廠實現:
//AnimalHouse
+ (AnimalHouse *)houseWithType:(AnimalType)type {
AnimalHouse *house = nil;
if (type == AnimalTypeDog) {//狗
house = [[DogHouse alloc] init];
} else if (type == AnimalTypeCat) {
house = [[CatHouse alloc] init];
} else if (type == AnimalTypeSheep) {
house = [[SheepHouse alloc] init];
}
return house;
}
具體使用:
//內部生成具體工廠`DogHouse `
// AnimalHouse *animalHouse = [AnimalHouse houseWithType:AnimalTypeDog];
//或者也可以直接使用具體工廠
AnimalHouse *animalHouse = [[DogHouse alloc] init];
//內部生成具體產品`MaleDog`
MaleAnimal* maleAnimal = [animalHouse maleAnimal];
//內部生成具體產品`femaleDog`
FemaleAnimal* femaleAnimal = [animalHouse femaleAnimal];
//使用該產品
[maleAnimal shout];
[femaleAnimal shout];
Cocoa下的應用:
Cocoa框架下使用的爲抽象工廠模式、具體使用的對象爲NSString
、NSArray
、NSDictionary
(包括可變對象)以及NSNumber
。
以數組爲例:
id obj1 = [NSArray alloc];
id obj2 = [NSMutableArray alloc];
id obj3 = [obj1 init];
id obj4 = [obj2 init];
id obj5 = [UIView alloc];
id obj6 = [obj5 init];
NSLog(@"%@",NSStringFromClass([obj1 class]));
NSLog(@"%@",NSStringFromClass([obj2 class]));
NSLog(@"%@",NSStringFromClass([obj3 class]));
NSLog(@"%@",NSStringFromClass([obj4 class]));
NSLog(@"%@",NSStringFromClass([obj5 class]));
NSLog(@"%@",NSStringFromClass([obj6 class]));
打印結果:
__NSPlaceholderArray
__NSPlaceholderArray
__NSArray0
__NSArrayM
UIView
UIView
可見數組與View不同。alloc生成的對象並不是最終的《產品》、而是一個《工廠》。
而且是一個單例工廠:
NSArray * obj1 = [NSArray alloc];
NSArray * obj2 = [NSArray alloc];
NSMutableArray * obj3 = [NSMutableArray alloc];
NSMutableArray * obj4 = [NSMutableArray alloc];
NSLog(@"%p",obj1);
NSLog(@"%p",obj2);
NSLog(@"%p",obj3);
NSLog(@"%p",obj4);
輸出:
0x604000010360
0x604000010360
0x604000010350
0x604000010350
策略模式(Strategy)
策略模式其實和工廠模式類似、都是利用繼承(或者協議)的方式實現。
只是《工廠模式更像是對對象的管理》、而《策略模式是對行爲的管理》。
舉個最常見的例子:AFNetworking下的AFHTTPRequestSerializer
與AFJSONResponseSerializer
、二者分別負責編碼與解碼的策略。
以解碼爲例、你可以使用不同的策略:
AFJSONResponseSerializer
、AFXMLParserResponseSerializer
、AFXMLDocumentResponseSerializer
等等。將服務器返回的數據解析成不同的結果。
在Cocoa下的應用:
數組排序的:sortedArrayUsingSelector
方法。
他會依居數組內部不同元素、採用不用元素的排序策略。
裝飾模式(Decorator)
是在不改變原封裝的前提下,爲對象動態添加新功能的模式
主要通過Extension
和Category
來實現
在Cocoa下的應用:
最常用的例子就是NSObject
的performSelector
方法集
NSObject (NSThreadPerformAdditions):
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
@interface NSObject (NSDelayedPerforming):
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
適配器模式(Adapter)
將一個類的接口轉化爲另一個類的接口、使得原本互不兼容的類可以通過接口一起工作
從某些意義上來講、某些情況下的代理模式也算適配器模式。
委託者
通過代理(適配器)
要求代理者
提供合適的資源。
適配器分爲:
- 類適配器
以(多)繼承的方式實現、被適配類的子類通過多繼承的方式進行格式化輸出。 - 對象適配器
存在一個適配器對象、用來將被適配對象進行格式化輸出。
實現一個適配器、我們至少需要以下三個對象:
1. 被適配者(Adoptee)
通常爲舊模塊
2. 適配目標(Target)
通常爲協議接口
3. 適配器(Adopter)
類適配器爲Adoptee的子類、對象適配器爲持有Adoptee的第三者。
4. 用戶(Client)
最終信息的接受者
在Cocoa下的應用:
UITableView(Client)
作爲向UIViewController
(Adopter
)尋求格式爲UITableViewDataSource(Target)
的資源。
而UIViewController
(Adopter
)、則通過對自身持有的數據源NSArray(Adoptee)
進行格式化處理後、交付給UITableViewDataSource(Target)
。
Demo的話可以看看《適配器模式的解析-iOS》或者《IOS設計模式淺析之適配器模式(Adapter)》
MVC及一些衍生設計模式
iOS架構補完計劃--淺談MVC及其衍生架構模式(附簡易圖解)
最後
本文主要是自己的學習與總結。如果文內存在紕漏、萬望留言斧正。如果不吝賜教小弟更加感謝。
參考資料
IOS設計模式淺析之簡單工廠模式(SimpleFactory)
iOS 三種工廠模式(簡單工廠模式、工廠模式、抽象工廠模式)
iOS設計模式之美-抽象工廠模式
【iOS開發】類簇--抽象工廠模式在OC中的使用
iOS策略設計模式
適配器模式的解析-iOS
IOS設計模式淺析之適配器模式(Adapter)
iOS架構師_適配器模式