• iPhone开发重构:从硬编码到模型到规律【转】


       无论在iPhone开发还是学习的过程中都会看到一些不是很理想的代码,不可否认自己也在不断“贡献”着这类代码。面对一些代码的“坏味道”,重构显然是 个有效的解决途径。《iPhone开发重构》系列就想总结和补充iPhone开发中经历的一些重构,其间可能会引用一些开源以及实际项目的代码,本着对技 术的探求,冒昧之处还请作者多多见谅。

        在iPhone开发的过程中经常会遇到根据不同的Table行或者标识符推入不同的Controller的需要,一个最直接的实现就是硬编码,通过if…else if…else或者switch…case…实现,代码如下:

    重构前:
    - (void)pushViewControllerWithIdentifier:(NSString *)identifier animated:(BOOL)animated {
        if ([identifier isEqualToString:@"Article"]) {
            viewController = [[WHArticleViewController alloc] initWithIdentifier:identifier];
        } else if ([identifier isEqualToString:@"SurvivalKit"]) {
            viewController = [[WHSurvivalKitViewController alloc] init];
        } else if ([identifier isEqualToString:@"Search"]) {
            viewController = [[WHSearchViewController alloc] initWithIdentifier:identifier];
        } else if ([identifier isEqualToString:@"Featured"]) {
            viewController = [[WHFeaturedViewController alloc] initWithIdentifier:identifier];
        } else if ([identifier isEqualToString:@"Image"]) {
            viewController = [[WHImageViewController alloc] initWithIdentifier:identifier];
        } else if ([identifier isEqualToString:@"Settings"]) {
            viewController = [[WHSettingsViewController alloc] init];
        }
        [self pushViewController:viewController animated:animated];
        [viewController release];
    }

        其中的“坏味道”就是过多的条件分支判断以及在各个分支中雷同的代码。在需要扩展的时候就要被迫修改代码,从而破坏了开放封闭原则。总结下规律后觉得应该 构建一个从identifier到对应的Controller名之间映射的表或者字典模型。实现的时候通过setupModel构建映射表,然后具体使用 的时候利用表进行映射,重构代码如下:

    重构一:

    - (void) setupModel {
        if(self.model == nil) {
            self.model = [NSDictionary dictionaryWithObjectsAndKeys:@"WHArticleViewController", @"Article",
                          @"WHSurvivalKitViewController", @"SurvivalKit",
                          @"WHSurvivalKitViewController", @"Search",
                          @"WHFeaturedViewController", @"Featured",
                          @"WHImageViewController", @"Image",
                          @"WHSettingsViewController", @"Settings",            
                          nil];
        }
    }

    - (void)pushViewControllerWithIdentifier:(NSString *)identifier animated:(BOOL)animated {
        NSString *identifierNamespace = [identifier identifierNamespace];
        NSString *controllerClassName = [self.model objectForKey:identifierNamespace];
        Class klass = NSClassFromString(controllerClassName);
        UIViewController *viewController = [[klass alloc] initWithIdentifier:identifier];
        [self pushViewController:viewController animated:animated];
        [viewController release];
    }

      重构后,不仅避免了过多的条件分支而且清理了各个分支中的雷同代码。不足就是表模型数据还是夹杂在代码中,因此希望通过plist文件隐藏这些和代码无关的数据。重构代码如下:

    重构二:

    - (void) setupModel{
        if(self.model == nil) {
            NSString *plistFilePath = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"plist"];
            self.model = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
        }
    }

    - (void)pushViewControllerWithIdentifier:(NSString *)identifier animated:(BOOL)animated {
        //实现同“重构一”
    }
     

       现在,一切看上去还挺美的。不过可能一段时间后会发现,原来indentifier和Controller名之间的映射是有规律的,所以可能根本不需要映射表。尝试一下吧!

    构三:

    - (void)pushViewControllerWithIdentifier:(NSString *)identifier animated:(BOOL)animated {
        NSString *identifierNamespace = [identifier identifierNamespace];
        NSString *controllerClassName = [NSString stringWithFormat:@"WH%@ViewController", identifierNamespace];
        Class klass = NSClassFromString(controllerClassName);
        UIViewController *viewController = [[klass alloc] initWithIdentifier:identifier];
        [self pushViewController:viewController animated:animated];
        [viewController release];
    }

         经过几个阶段的重构,代码不仅“瘦身”了,而且逻辑更清晰了。通过这样一个从硬编码到模型到规律的过程,大家看到的应该不仅仅是不断改进的代码,而且还会 感觉到重构的迭代性和无止境吧!任何的设计和实现都只能是在某种情境和阶段是合理的,而不存在一个永远完美的答案。

    本文出自 “林家男孩” 博客,请务必保留此出处http://bj007.blog.51cto.com/1701577/545537

  • 相关阅读:
    将1、2、3、……、n这n个连续自然数分成g组,使每组的和相等。g组中个数最多的一组有几个?
    磁带机、驱动器、磁带库、机械手之间的区别
    Mysql基础命令
    pip 加速下载
    NBU命令之 nbftconfig :配置与光纤传输 (FT) 服务器和 SAN 客户端相关的属性
    IEDriverServer.exe驱动问题汇总
    系统集成项目管理工程师考试2020介绍
    LTO1,LTO2,LTO3,LTO4,LTO5 LTO6 磁带读写速度和兼容性及LTO6主要参数
    Mysql 备份方式 MySQL Agent & MySQL Enterprise Backup & Percona XtraBackup
    Netbackuk命令之bpclntcmd
  • 原文地址:https://www.cnblogs.com/simonshi2012/p/2269339.html
Copyright © 2020-2023  润新知