【问题标题】:Singleton Instance vs Class Methods单例实例与类方法
【发布时间】:2012-10-22 17:50:16
【问题描述】:

最近在使用 Objective-C 和用它编写的各种库时,我注意到两种非常流行的单例模式。一个版本获取单例实例并调用它的实例方法,而另一个版本只公开类方法,从不给你一个实例来使用。所有这些都具有抽象对单个资源(StoreKit、CoreData、Parse API 等)的访问的目的。例如,这是 MKStoreKit 中使用的前一种方法:

// initialize singleton during app boot
[MKStoreManager sharedManager]

// sometime later in the app
[[MKStoreManager sharedManager] buyFeature:kFeatureAId 
                                onComplete:^(NSString* purchasedFeature)
 {
     NSLog(@"Purchased: %@", purchasedFeature);
 }
                               onCancelled:^
 {
     NSLog(@"User Cancelled Transaction");
 }];

或者 NSUserDefaults、UIApplication 等。另一种方法可以在 MagicalRecord 或此处使用 Parse API 看到:

// configure API credentials sometime during app boot
[Parse setApplicationId:@"123456"
              clientKey:@"123456"];

// sometime later
PFObject *testObject = [PFObject objectWithClassName:@"TestObject"];
[testObject setObject:@"bar" forKey:@"foo"];
[testObject save];

这两种方法有哪些优缺点,其中一种从根本上优于另一种?

不必检索共享实例可以节省一些屏幕空间(性能差异可能无关紧要),但我是否以其他方式搞砸了自己,例如可测试性?

谢谢!

【问题讨论】:

    标签: objective-c oop design-patterns


    【解决方案1】:

    有两种不同的方式来实现基于类方法的方法:

    • 使用对所有人隐藏的类创建单例实例,并将其方法隐藏在具有相同签名的包装类方法后面,或者
    • 制作完成所有工作的类方法

    第一个实现的含义是,你可以用单例做的所有事情,你都可以用隐藏的单例做:

    • 使用子类成为可能
    • 在运行过程中切换实例很容易
    • 状态存在于实例变量中
    • 初始化遵循熟悉的模式

    如果您选择不使用单例的实现,您将依赖静态变量来保持当前状态。这是一个合理的选择,但是初始化模式变得不同(甚至可能使用dispatch_once),如果不依赖一些丑陋的if 条件,您无法在中间切换实现,并且使用子类变得更加棘手。

    测试第一个实现比测试第二个实现要容易一些,因为您可以提供一个单独的单例实现进行测试,也许通过后门;对于基于静态的实现,无法采用此路由。

    总而言之,我将使用基于单例的解决方案,单例可选地隐藏在提供对单例方法的访问的“外观”后面。我不会使用所有状态都必须放在静态变量中的实现。

    【讨论】:

    • 不错的答案,但一个小例子会让它更容易理解。
    【解决方案2】:

    单例方法的一个优点是,如果需要,允许其他实例变得微不足道。如果您采用类方法方法,则无需进行大量重构即可获得全部内容。

    【讨论】:

      猜你喜欢
      • 2011-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-18
      • 1970-01-01
      相关资源
      最近更新 更多