单例实例与类方法

在最近使用Objective-C和其中编写的各种库时,我注意到了两个非常stream行的单例模式。 一个版本获取单例实例并调用其实例方法,而其他版本只暴露类方法,从不给你一个实例。 所有这些都具有抽象访问单个资源(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]; 

这两种方法有什么优点和缺点,其中之一是从根本上优于另一种呢?

不必检索共享实例可以节省一些屏幕资源(性能差异可能不相关),但是我是否以其他方式搞砸了自己,例如可testing性?

谢谢!

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

  • 使用隐藏的类来创build一个单例实例,并将其方法隐藏在具有相同签名的包装类方法后面
  • 做出所有工作的类方法

第一个实现的含义是,你可以用一个单例做什么,你可以使用隐藏的单例:

  • 使用子类成为可能
  • 在运行过程中切换实例很容易
  • 国家居住在实例variables
  • 初始化遵循熟悉的模式

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

testing第一个实现比testing第二个实现要容易一些,因为你可以提供单独的testing实现,也许通过后门; 与一个基于静态的实现,这条路线不能采取。

总而言之,我将使用基于单例的解决scheme,单身人士可以隐藏在提供访问单身人士方法的“门面”之后。 我不会使用一个所有状态必须放在静态variables中的实现。

单例方法的一个优点是,如果需要的话,允许其他实例变得微不足道。 如果你采用类方法,这就是所有你没有很多的重构。