我一直在想同样的事情,我想我有一个答案给你。
这取决于你需要用它做什么。两者都不一定更“正确”。
如果您想了解我如何得出结论的详细信息,请继续阅读或向下滚动到tl;dr部分。
正如您所说,访问单例以让班级为您管理单例似乎(外部)不那么麻烦。本质上,您可以通过用初始化方法替换单例的工厂方法来做到这一点。查看Apple在这方面的文档,您可以看到他们在哪里显示了一种“共享”方法,该方法充当工厂根据需要生产单例。
static MyGizmoClass *sharedGizmoManager = nil;
+ (MyGizmoClass*)sharedManager
{
if (sharedGizmoManager == nil) {
sharedGizmoManager = [[super allocWithZone:NULL] init];
}
return sharedGizmoManager;
}
您可以使用 void 初始化程序替换该方法,而不是这样做:
+ (void)initializeMyGizmo
{
if (sharedGizmoManager == nil) {
sharedGizmoManager = [[super allocWithZone:NULL] init];
}
// whatever else needs to be done to the singleton to initialize it
}
然后只使用类方法并允许MyGizmoClass
管理对单例的更新,例如[MyGizmoClass setGizmoName:@"Gadget"]
.
注意:在这种情况下,查看文件以查看属性的人会感到困惑.h
,在这种情况下,他们可能会得出结论,他们应该自己创建对象的实例,或者能够在某些情况下访问单例形式或时尚。因此,如果您要走封装对单例的访问的路线,那么使用公共变量是不明智的。
到那时:
如果您确实仅通过类本身限制访问,您将丢失任何 getter 和 setter 或其他随属性一起提供的免费东西。这意味着,如果MyGizmoClass
要将其作为模型的一部分,NSString *gizmoName
您将被迫为此“属性”创建自定义 getter 和 setter,并将其作为 ivar 或属性保存在.m
文件(即私有)的接口扩展中单例类,或作为相邻的静态变量。
所以这引出了一个问题(这也是让我首先思考的问题),我们是否应该完全包含该行static MyGizmoClass *sharedGizmoManager = nil;
,或者我们是否可以完全取消内部接口扩展并替换我们想要限制访问的任何可能的 ivars 或属性static
实施中的实施?
我已经回答了...
这取决于你需要用它做什么。
tl;博士
第一个场景
如果您曾经(即使是最微小的机会)需要将您的子类
TextureManager
化或可以创建它的多个实例(使其不再是单例),最好坚持常规的 Apple 单例约定。
这包括多个“singleton”,其中您可能有几个
TextureManager
预先配置了不同设置的s。
在这种情况下,您将根据需要(公开或私下)使用属性以及 ivars。您也可以混合使用 ivars 和静态变量,但您仍然需要TextureManager
在实现内部有一个静态实例TextureManager
。
第二个场景
如果您只需要一个实例并且 TextureManager
它将完全独立运行而不会进一步混合,那么您可以在.m
文件的实现中完全删除类的静态实例,并用其中的静态变量替换 ivars 和属性执行。
如果您将属性或设置存储在 CoreData 中并且只需要它们进行配置,这将很有用。
请记住,在这种情况下,您必须为静态变量创建所有 getter 和 setter,并且只能使用类方法访问它们(但这就是重点)。
其他有趣的东西
这个答案为何时以及如何调用“initializer”方法或创建单例的问题提供了一个有趣的解决方案。这可以与每个场景一起使用,以在第一个场景中初始化单例,或者在第二个场景中将默认值预加载到类级静态中。
如果您想在实现中坚持使用静态单例,您可以查看这篇文章,让您更好地了解单例的真正“全局范围”。