gpt4 book ai didi

Objective-C:使用单例还是使用类作为对象?

转载 作者:太空狗 更新时间:2023-10-30 03:19:12 24 4
gpt4 key购买 nike

我一直想知道在什么情况下真的有必要在 Objective-C 中采用单例模式(例如,定义一个专用类并创建一个单个实例),而将类用作对象是行不通的。

特别是,我正在考虑以下解决方案:

  • 定义和使用适当的类方法,而不是单例实例上的实例方法;
  • 使用 static变量(文件范围全局变量),而不是单例实例的实例变量;
  • 在注册为通知观察者时使用类对象,而不是单例实例。尽管类对象本身就是一个 Objective-C 对象(对吗?),但这需要注册的通知处理程序是类方法; (这可能吗?)

  • 例如,而不是拥有 Texture类(模型对象) TextureManager单例(资源管理器),您可以将所有纹理创建/清理实现为相同的类方法和静态变量 Texture类(工厂模式加上一些资源管理)。

    对这个设计有什么想法吗?

    编辑:
    现在想起来,还是在 Texture上面的例子,即使我将两个类分开( TextureTextureManager )我也必须在 A. 让管理器成为单例,并使用实例方法操作它,或 B. 让管理器成为无实例,辅助类。澄清:
    Texture* myTexture = [[TextureManager defaultManager] textureWithName:@"TextureName"]; 
    // (singleton, client uses instance methods)

    相对
    Texture* myTexture = [TextureManager textureWithName:@"TextureName"]; 
    // (Class standing in for singleton, client uses class methods)

    后者看起来更直接,不那么麻烦/冗长,但我想知道哪种设计“更正确”。当然,前者允许多个 TextureManager实例是否需要出现(不是在我的情况下)。

    最佳答案

    我一直在思考同样的事情,我想我有一个答案。

    这取决于你需要用它做什么。 两者都不一定更“正确”。

    如果您想了解我如何得出结论的详细信息,请继续阅读或向下滚动到 tl;博士 部分。

    正如您所说,访问单例让类(class)为您管理单例似乎(从外部)不那么麻烦。基本上你可以通过用初始化方法替换单例的工厂方法来做到这一点。看着 Apple's documentation在此您可以看到他们在何处展示了“共享”方法,该方法充当根据需要生成单例的工厂。

    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 的人会感到困惑。文件以查看属性,在这种情况下,他们可能会得出结论,他们应该自己创建对象的实例,或者能够以某种形式或方式访问单例。所以 如果 你要走封装对单例的访问的路线,使用公共(public)变量是不明智的。

    到那一点:

    如果您确实仅通过类本身限制访问,您将丢失任何 getter 和 setter 或其他随属性而来的免费内容。这意味着如果 MyGizmoClass作为其模型的一部分, NSString *gizmoName您将被迫为此“属性”创建自定义 getter 和 setter,并将其作为 ivar 或属性保存在 .m 的接口(interface)扩展中。单例类的文件(即私有(private)),或作为相邻的静态变量。

    所以这就引出了一个问题(这也是让我首先思考的问题),我们是否应该包括行 static MyGizmoClass *sharedGizmoManager = nil;或者我们可以完全取消内部接口(interface)扩展并替换我们想要限制访问的任何可能的变量或属性 static执行中的执行?

    我已经回答了...

    It depends on what you need to do with it.



    tl;博士

    第一个场景

    如果您曾经(即使是最微小的机会)需要将您的 TextureManager或者可以创建它的多个实例(使其
    不再是单例)最好坚持常规
    单例的 Apple 约定。

    这包括多个“单例”,其中您可能有几个 TextureManager s 预先配置了不同的设置。

    在这种情况下,您可以根据需要使用属性(公开或
    私下)以及ivars。你也可以混合使用 ivars 和
    静态,但你仍然需要有一个静态实例
    您的 TextureManager内部 TextureManager执行。

    第二个场景

    如果您 将永远需要 TextureManager 的实例并且它将完全独立运行,不会进一步混合,然后您可以在 .m 中的实现中完全删除您的类的静态实例|文件并用该实现中的静态变量替换 ivars 和属性。

    如果您将关闭的属性或设置存储在 CoreData 中并且只需要它们进行配置,这会很有用。

    只要记住 在这种情况下,您必须为静态变量创建所有 getter 和 setter,并且只能使用类方法访问它们(但这就是重点)。

    其他有趣的东西

    This answer为何时以及如何调用“初始化程序”方法或创建单例的问题提供了一个有趣的解决方案。这可以与每个场景一起使用,以在第一个场景中初始化单例,或者在第二个场景中将默认值预加载到类级静态中。

    如果您想在实现中坚持使用静态单例,您可以查看 this article让您更好地了解单例的真正“全局范围”。

    关于Objective-C:使用单例还是使用类作为对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18798889/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com