使用单例作为数据管理器类坏吗?

时间:2012-01-03 04:23:25

标签: ios objective-c design-patterns singleton

我经常创建需要存储数据的应用程序,并且这些数据用于整个程序。但是,它并不多,所以我通常使用NSUserDefaults来加载/保存这些数据。但是,保存/加载代码以及打包/解包数据会占用空间,我认为将此代码移动到全局单例内的可重用方法将是一个好主意。它似乎运作良好。

即便如此,我最近还是对单身人士和全球物体的祸害进行了很多阅读,并且我已经开始有了第二个想法。人们常说,单身人士的使用几乎总是表明设计不佳。在大多数情况下,我不同意(我认为像这样的简单用法是一个很好的设计模式),但我当然不是这方面的专家。

那么,即使是像这样糟糕的简单方式使用单身人士呢?如果是这样,那么更好的替代方案是什么?

1 个答案:

答案 0 :(得分:5)

我绝对不同意单身人士是邪恶的。它们有时可能被过度使用,但在某些情况下它们对于工作来说是完美的。在某些应用程序中,拥有某种通用数据管理器是有意义的。单例模式广泛用于SDK本身(应用程序委托,共享管理器,默认中心等)。大多数情况下,这些不是“纯粹的”单例,因为您可以访问共享实例,但如果需要也可以创建新实例。

您需要问自己的问题是,在任何时间从任何地方访问数据管理器的单个实例是否有用,如果不是,则可能不需要单个实例。如果你打算在多线程环境中使用单例,你需要担心竞争条件(一个线程可以修改资源而另一个访问它),文档对如何在Cocoa中实现这一目标有很好的解释

让我试着用一个例子来解释 - 我使用了我写的游戏中的一些代码。假设您有一个GameMap类和一个Tile类。 GameMap代表Tile个对象的二维网格。

GameMap *gameMap = [[GameMap alloc] init];
NSArray *theTiles = gameMap.tiles;

GameMap的实例拥有图块网格,并在创建游戏地图时创建图块。不需要单身人士。

你可能会说“但我一次只有一个GameMap,这有什么大不了的?”。加载已保存的游戏或加载新关卡怎么样?好吧,这变得如此简单:

// In whatever class object owns the game map
self.gameMap = [[GameMap alloc] initWithSaveData:saveData];

总之,创建一个具有代码来管理其他事物实例的类的实例。保持尽可能全局化,您的代码将更具可扩展性和可维护性。