iOS架構補完計劃--設計模式

目錄

  • 官方用到的幾種設計模式
    • 代理模式(Proxy)
    • 觀察者模式(Observer)
    • 單例模式(Singleton)
    • 工廠模式(Factory)
    • 策略模式(Strategy)
    • 裝飾模式(Decorator)
    • 適配器模式(Adapter)
    • MVC及一些衍生設計模式

官方用到的幾種設計模式

官方的用法總是我們很關心、也是值得學習的


代理模式(Proxy Pattern)

當一個類的某些功能需要由別的類來實現、但是又不確定具體會是哪個類實現。

有兩個主體:委託者(方法調用者)、代理者(方法實現者)。

Cocoa下的應用:

UITableView、UIAlertView、NSURLSession等等


觀察者模式(Observer)

主要負責對象間的通訊。

觀察者註冊自己感興趣的事件、被觀察者不需要知道觀察者的存在。

  • 通知

Cocoa下的應用:

鍵盤升降(UIKeyboardWillShowNotificationUIKeyboardWillHideNotification)、前後臺切換(name:UIApplicationDidEnterBackgroundNotificationUIApplicationDidBecomeActiveNotification)等等

  • 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框架下使用的爲抽象工廠模式、具體使用的對象爲NSStringNSArrayNSDictionary(包括可變對象)以及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下的AFHTTPRequestSerializerAFJSONResponseSerializer、二者分別負責編碼與解碼的策略。

以解碼爲例、你可以使用不同的策略:
AFJSONResponseSerializerAFXMLParserResponseSerializerAFXMLDocumentResponseSerializer等等。將服務器返回的數據解析成不同的結果。

在Cocoa下的應用:

數組排序的:sortedArrayUsingSelector方法。
他會依居數組內部不同元素、採用不用元素的排序策略。


裝飾模式(Decorator)

是在不改變原封裝的前提下,爲對象動態添加新功能的模式

主要通過ExtensionCategory來實現

在Cocoa下的應用:

最常用的例子就是NSObjectperformSelector方法集
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架構師_適配器模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章