Objective-C中Singleton的替代scheme,用于更好的应用程序devise

看来很多Objective-C代码现在都在使用Singleton。

虽然有很多人抱怨Singleton,比如说Google( 所有Singletons都去哪了? ),但他们的工程师同样也使用它: http : //code.google.com/mobile/analytics/docs/iphone/

我知道我们在Stack Overflow中已经有了一些答案,但是它们并不完全针对Objective-C作为dynamic语言:Objective C具有类别,而许多其他语言则不具备这些类别。

那么你有什么看法? 你还用单身吗? 如果是这样,你怎么让你的应用程序更易于testing?

更新 :我认为我们需要用代码作为更具体的讨论的例子,所以关于SO的很多讨论都是基于理论的,没有一行代码

让我们以Google Analytics iOS SDK为例:

// Initialization [[GANTracker sharedTracker] startTrackerWithAccountID:@"UA-0000000-1" dispatchPeriod:kGANDispatchPeriodSec delegate:nil]; // Track page view [[GANTracker sharedTracker] trackPageview:@"/app_entry_point" withError:&error]; 

上述代码的优点在于,使用方法“ startTrackerWithAccountID ”进行初始化后,您可以在应用程序中运行方法“ trackPageview ”,而无需通过configuration。

如果你认为辛格尔顿是不好的,你可以改进上面的代码吗?

非常感谢您的意见,周五愉快。

这个post可能是downvote诱饵,但我不明白为什么singletons得不到爱。 他们是完全有效的,你只需要了解他们有用的东西。

在iOS开发中,您现在只有一个应用程序实例。 你只有一个应用程序,对吗? 你不是两个或零申请,是吗? 所以这个框架为您提供了一个UIApplication单例,通过它可以获得应用程序级别的操作系统和框架function。 它模拟一些适当的东西,使之成为一个单身人士。

如果你的数据字段只能有一个,而且你需要从你的应用程序的所有地方find它们,那么把它作为一个单例模型也是完全没有问题的。 创build一个单身作为一个全局性的桶可能是滥用模式,我认为这可能是大多数人反对他们。 但是,如果你正在build立一个“单一”的东西,那么一个单身人士可能就是要走的路。

一些开发者似乎对单身人士有一个基本的厌恶,但是当真正被问到为什么时,他们会咕glob一些关于全局和名称空间和美学的东西。 我想我可以理解,如果你真的彻底解决了单身人士是一种反模式,并在所有情况下被憎恨。 但是在那个时候你还没有想到。 而框架devise不同意你的看法。

我认为大多数开发人员都经历了Singleton阶段,在这里你可以获得所需要的所有东西,就像一堆精彩的单身人士一样。

然后你发现单身testing可能很困难。 你实际上不想连接到数据库,但你的单身。 添加一层redirect和模拟它。

然后你会发现unit testing不是唯一需要不同行为的时候。 你可以让你的Singleton根据参数configuration不同的行为。 你开始怀疑你是否需要把它分成两个单例。 然后你的代码需要知道使用哪个单例,所以你需要一个知道使用哪个单例的单例。

然后,一些其他的代码开始搞乱你的单例中的值,而你正在使用它。 他们怎么敢! 如果你只是想让任何人从任何地方获得这些价值,那么你就可以让他们成为全球化的…

一旦你到了这一点,你开始怀疑单身汉是否是正确的解决scheme。 你开始看到全球数据的危险,特别是在面向对象的devise中,你只是假设你的数据不会被其他人嘲笑。

所以你回去开始传递数据,而不是查看它(以前被称为良好的OOdevise,但现在它有一个像“dependency injection”这样的花式名称)。

最终你会了解到单身男人适可而止。 你学会识别你的Singleton需要什么时候停止单身。

所以你得到像UIApplication和NSUserDefaults这样的共享对象。 这些是单身人士的好用途。

我十年前在Java Singleton狂热中被烧得够呛。 我甚至不考虑写自己的单身人士。 我只需要在最近的内存中需要任何类似的东西,想caching[NSCalendar currentCalendar]的结果(这需要很长的时间)。 我在NSCalendar上创build了一个类,并将其作为一个静态variables进行caching。 我觉得有点肮脏,但替代是痛苦的慢代码。

总结和为那些谁;博士:

单身人士是一个工具。 他们不太可能是正确的工具,但你必须为自己发现。

为什么你需要一个答案是“完全客观C具体”? 单身并不完全是Obj-C的特定,你可以使用这些。 函数不是Obj-C特有的,整数不是Obj-C特有的,但是你可以在你的Obj-C代码中使用所有这些。

任何语言的单身工作的明显替代。

一个单身人士是一个devise糟糕的全球。

所以最简单的替代scheme就是使其成为一个普通的全球性的,没有愚蠢的“一个实例”的限制。

更彻底的解决scheme是,而不是全局可访问的对象,而是将其作为parameter passing给需要它的函数。

最后,您可以使用dependency injection框架来实现混合解决scheme。

单身人士的问题是他们导致紧密的联系。 假设您正在build立一个航class预订系统:您的预订控制器可能会使用一个

 id<FlightsClient> 

在控制器内获取它的常用方法如下:

 _flightsClient = [FlightsClient sharedInstance]; 

缺点:

  • 单独testing一个class级变得很困难。
  • 如果您想更改另一个实施的飞行客户端,则需要search该应用程序并将其逐个更换。
  • 如果有应用程序应该使用不同的实现(例如,OnlineFlightClient,OfflineFlightClient)的情况下,事情变得棘手。

一个很好的解决方法是应用dependency injectiondevise模式。

想想dependency injection讲述一个build筑故事 。 当应用程序中的关键angular色被拉入程序集时,应用程序的configuration就会正确模块化(消除重复)。 创build了这个脚本后,现在很容易重新configuration或交换一个angular色。“ 通过这种方式,我们不需要一次性理解所有的问题,而且随着需求的发展,我们的应用程序的devise也变得很容易。

这是一个dependency injection库: https : //github.com/typhoon-framework/Typhoon