【问题标题】:Static Class vs Singleton [duplicate]静态类与单例 [重复]
【发布时间】:2013-08-19 07:58:29
【问题描述】:

所以,很简单的问题。忽略过度使用单例模式的影响。我试图在 Objective-C 中找到一个可靠的单例模式。我遇到过这个:

@implementation SomeSingleTonClass

static SomeSingleTonClass* singleInstance;

+ (SomeSingleTonClass*)getInstance
{
    static dispatch_once_t dispatchOnceToken;

    dispatch_once(&dispatchOnceToken, ^{
        singleInstance = [[SomeSingleTonClass alloc] init];
    });

    return singleInstance;
}

- (void)someMethodOnTheInstance
{
    NSLog(@"DO SOMET WORK")
}

@end

我对此很满意,但它导致了很多这样的事情:

[[SomeSingleTonClass getInstance] someMethodOnTheInstance];

我的问题是,为什么这比纯静态类更好。

@implementation SomeStaticClass

static NSString* someStaticStateVariable;

- (id)init
{
    //Don't allow init to initialize any memory state
    //Perhaps throw an exception to let some other programmer know
    //not to do this
    return nil;
}

+ (void)someStaticMethod
{
    NSLog(@"Do Some Work");
}

您真正获得的只是看起来更干净的方法调用。基本上你换掉这个:

[[SomeSingleTonClass getInstance] someMethodOnTheInstance];

为此

[SomeStaticClass someStaticMethod];

这肯定是一个小的简化,您始终可以将实例存储在您的类中。这更像是一种求知欲,我用静态类而不是单例来惹恼什么 Objective-C 上帝?我敢肯定我不能成为第一个想到这个的人,但我保证,我先做了重复搜索。我发现的几个答案,我觉得是基于旧版本的可可,因为即使是讨论过的单例模式似乎也存在线程问题。

【问题讨论】:

  • 我认为你是对的,但这个问题有点令人费解(尽管答案很可靠!)。我要留下我的,但鉴于该线程中的答案,我不需要等待鼓手回答的赞成票。这是正确的。谢谢!
  • 什么是静态类?
  • 一个静态类(可能有更好的名字)是一个依赖于类方法和静态类变量的类,而不是一个实例化的对象和实例方法。这就是使它成为一个方便的单例的原因。特别是如果您编写 init 方法以引发异常!
  • 虽然我怀疑你是否会惹恼任何 ObjC 之神(至少不是很多 ;-)),但“静态类”是错误的命名法——在 Objective-C 中没有这样的东西。
  • 作为推论,Objective-C 有类方法,但在 Objective-C 中没有静态方法。

标签: ios objective-c macos cocoa


【解决方案1】:

静态类:当您想要将独立于状态的实用方法组合在一起时使用。

单例:当您有多个共享状态的方法时使用。

【讨论】:

    【解决方案2】:

    我发现两者结合起来很方便。我使用与您的第一个类似的标准单例模式,结果是:

    [[MyClass defaultInstance] doSomething];
    

    但我也希望能够创建同一类的其他实例:

    MyClass *secondInstance = [[MyClass alloc] init];
    [secondInstance doSomething];
    

    当我想要更简洁地访问单例实例上的调用方法时,我定义类方法如下:

    // class method to call a method on the singleton instance
    + (void)doSomething
    {
        [[MyClass defaultInstance] doSomething];
    }
    

    因此,我可以使用:

    [MyClass doSomething];
    

    【讨论】:

      【解决方案3】:

      这样的课程不会惹恼任何 Objective-C 之神。实际上,Apple 建议在某些情况下使用该模式(我认为他们在 ARC 会议视频之一中提到了这一点,他们讨论了常见的设计模式以及如何使用 ARC 实现它们)。

      在其他情况下,您可以拥有一个类的多个实例,但想要一个默认实例,您当然必须使用共享实例方法。

      【讨论】:

      • 基本正确。此外,请参阅 Martin 提供的“重复”链接中的答案,了解每个链接的影响。看起来这两种方法实际上都没有更好或更坏,只是不同。
      • 没有人指出的一件事是,一个不平凡的单例(与静态类相反)可以做更多的事情,因为它是一个合法的实例。注册通知、键值观察、用作数据源等
      • 当你说“那个模式”时,你在说哪个该死的模式?哈哈。他在帖子中放了两种不同的模式。
      【解决方案4】:

      第一个例子似乎是不必要地创建一个类的单例实例。我说是不必要的,因为从您的其他 cmets 看来,该类没有声明任何属性或实例变量。鉴于对象的基本目的是为状态提供存储,没有实例变量的对象很少有用。

      您的第二个示例显示了一个永远不会被实例化的类。同样,Objective-C 中类的基本目的是充当实例的工厂,因此从未实例化的类并不是真正有用或必要的。

      相反,您可以只提供一组 C 函数。 C 函数根本不需要与类关联。所以考虑做这样的事情:

      static NSString* someStaticStateVariable;
      
      void someFunction(void)
      {
          NSLog(@"Do Some Work");
      }
      

      函数可以在单独的 .h/.m 对中,或者可以合并到现有类的 .h/.m 中,如果这样做有意义的话(通常,如果函数与关注点密切相关该类的)。

      【讨论】:

      • 课程的演示只是为了演示我正在考虑的设计模式,而不是我正在考虑的用途。为了堆栈溢出问题,我当然希望我的类比我在简化示例中呈现的状态多得多。
      • @ChrisCM 您似乎是在说您的实例将具有状态,但在您的第二个示例中,您覆盖 init 以禁用创建实例,因此显然不可能拥有具有状态的对象。你不能给一个类添加状态,所以剩下的就是全局变量。同样,您不需要类和方法来使用全局变量,那么为什么不直接使用 C 函数呢?
      • 我想它最终没有回答这个问题。两种解决方案都可能存在相同的缺陷,即将状态存储在静态全局变量中。这就是“为什么/为什么不?”我很好奇,而不是如何。那么,为什么不使用纯 C 函数呢?因为,将某些东西与类相关联对于更清晰地理解代码本质上是有用的。 [MyDatabaseClass someFunction] 比 someFunction() 更能告诉我正在发生的事情。
      猜你喜欢
      • 2011-02-23
      • 2010-10-25
      • 1970-01-01
      • 2011-05-17
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 2018-04-29
      • 1970-01-01
      相关资源
      最近更新 更多