在 XMind iOS 版开发过程中, 需要对不同的布局方式选择不同的类来进行布局,所以需要用到策略模式来处理。在开发过程中,找到了一种还不错的解决方式。
在 XMind 思维导图中,每一个 topic 都包含一个布局的名称,被称为 structure
,我们为各种布局设计了不同的布局类来布局,这里称为 layout
。
最初的处理方法
最开始开发的过程中,我在 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 ) 或者新增策略的话,只需要继续给 LayoutBase 加子类即可,不需要需要其他类,实现了解耦合。示例代码如下,
在父类中提供注册和查询的类方法。
@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的区别
进一步优化
一般情况下,策略选择不会是 key 和 class 一一对应着么简单。可能还要考虑各种因素加入算法进行策略选择。把策略选择这个职责交给一个单独的类来处理,我们这里把它叫做 layoutSelector。Controller 在选择策略时,发消息给 layoutSelector,然后由 layoutSelector 进行处理将选好的策略返回。
Layout *layout = [controller installLayoutWithConditions: (NSDictionary *)conditionsDict];
欢迎来我的个站逛逛: http://alexyu.me/
网友评论