如何优雅地实现策略模式

作者: dreamCatcher | 来源:发表于2015-04-27 00:25 被阅读4087次

在 XMind iOS 版开发过程中, 需要对不同的布局方式选择不同的类来进行布局,所以需要用到策略模式来处理。在开发过程中,找到了一种还不错的解决方式。

在 XMind 思维导图中,每一个 topic 都包含一个布局的名称,被称为 structure,我们为各种布局设计了不同的布局类来布局,这里称为 layout

最初的处理方法

最开始开发的过程中,我在 controller 中定义了一个 NSDictionary,用于存放 structureNamelayout 的对应关系。

@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/

相关文章

  • 如何优雅地实现策略模式

    在 XMind iOS 版开发过程中, 需要对不同的布局方式选择不同的类来进行布局,所以需要用到策略模式来处理。在...

  • 【设计模式】优雅的策略模式

    借助强大的Spring,优雅地使用策略模式 啥是佩奇 策略模式 维基百科:Strategy pattern菜鸟教程...

  • 策略模式

    一 简介 1.定义 策略模式属于对象的行为模式.策略模式能在运行时改变软件的算法行为.如何实现策略模式根据情况而...

  • 使用lambda表达式重构面向对象的设计模式(一)

    策略模式重构 策略模式中的策略在编程中其实就是算法,使用Sttrategy模式可以整体地替换算法的实现部分。能够整...

  • 行为型-Strategy

    策略模式的原理与实现 策略模式的原理与实现策略模式,英文全称是 Strategy Design Pattern。在...

  • Spring优雅的实现策略模式

    源码 https://github.com/shawntime/shawn-design-pattern/ 定义 ...

  • 简短优雅地利用js实现 sleep 函数

    简短优雅地实现 sleep 函数 很多语言都有 sleep 函数,显然 js 没有,那么如何能简短优雅地实现这个方...

  • 设计模式(策略模式)

    策略模式的重点不是实现算法,而是如何调用算法。 策略模式主要分三大类:1.环境角色类(context)直接和客户端...

  • 如何优雅

    如何优雅?这是一个很流行,也很值得追问的问题。 如何优雅地读书?如何优雅地喝茶?如何优雅地跑步?如何优雅地追求女神...

  • 设计模式 | 策略模式及典型应用

    本文的主要内容: 介绍策略模式 示例商场购物打折策略的实现 策略模式总结 源码分析策略模式的典型应用Java Co...

网友评论

    本文标题:如何优雅地实现策略模式

    本文链接:https://www.haomeiwen.com/subject/nwkotttx.html