在 XMind iOS 版開發(fā)過程中, 需要對不同的布局方式選擇不同的類來進行布局,所以需要用到策略模式來處理。在開發(fā)過程中湾宙,找到了一種還不錯的解決方式。
在 XMind 思維導圖中,每一個 topic 都包含一個布局的名稱侠鳄,被稱為 structure
埠啃,我們?yōu)楦鞣N布局設計了不同的布局類來布局,這里稱為 layout
伟恶。
最初的處理方法
最開始開發(fā)的過程中碴开,我在 controller
中定義了一個 NSDictionary
,用于存放 structureName
和 layout
的對應關系博秫。
@property (nonamatic, strong) NSDictionary *structureDict;
- (instance)init {
self = [super init];
_structureDict = @{ structureNameA : LayoutA,
structureNameB : LayoutB,
structureNameC : LayoutC,
structureNameD : LayoutD,
structureNameE : LayoutE};
}
這種方式的確可以避免太多的 if else 的選擇結構潦牛。但是, controller還是必須要知道各個策略類挡育,假如 structureName 有變化巴碗,或者新增一種策略 (layout class) 的時候,需要去修改 controller 的策略 structureDict静盅,并且需要導入新的策略類良价。
解耦的處理方法
后來經 @Frank 提醒,找到了一種更好的方式來處理此類策略選擇問題蒿叠。每個策略子類自行將自己以及對應的 strucutreName 作為 key 注冊到共同父類 LayoutBase class 中的字典中去明垢。這樣以來,策略有變化 (如 structureNameA 需要選擇策略 LayoutC ) 或者新增策略的話市咽,只需要繼續(xù)給 LayoutBase 加子類即可痊银,不需要需要其他類,實現(xiàn)了解耦合施绎。示例代碼如下溯革,
在父類中提供注冊和查詢的類方法。
@implementation LayoutBase
static NSMutableDictionary *subClassDict = nil;
+ (void)registerLayout:(Class)layout withKey:(NSString *)key {
if (subClassDict == nil)
{
subClassDict = [[NSMutableDictionary alloc] init];
}
[subClassDict setObject:layout forKey:key];
}
+ (Class)layoutClassWithKey:(NSString *)key {
if ([subClassDict objectForKey:key]) {
Class class = [subClassDict objectForKey:key];
return class;
}
return nil;
}
@end
子類則需要在 load 的方法中谷醉,將自己注冊到 subClassDict 中致稀。
@implementation LayoutA
+ (void)load {
[LayoutBase registerLayout:self withKey:structureNameA];
}
@end
什么是 load 方法?
上述處理方法中我們用到了類的 load
方法俱尼。load
方法是一個特殊類方法抖单。
runtime 會在程序運行一開始對所有引用的 class 調用其 load 方法一次。所以可以利用這個方法進行一些預處理工作遇八。官方的介紹矛绘,
Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
詳情請移步:Apple 官方介紹
還可參考:Ider的博客 Objective C類方法load和initialize的區(qū)別
進一步優(yōu)化
一般情況下,策略選擇不會是 key 和 class 一一對應著么簡單刃永』醢可能還要考慮各種因素加入算法進行策略選擇。把策略選擇這個職責交給一個單獨的類來處理斯够,我們這里把它叫做 layoutSelector囚玫。Controller 在選擇策略時喧锦,發(fā)消息給 layoutSelector,然后由 layoutSelector 進行處理將選好的策略返回劫灶。
Layout *layout = [controller installLayoutWithConditions: (NSDictionary *)conditionsDict];
歡迎來我的個站逛逛: http://alexyu.me/