【问题标题】:Objective C Singleton with class hierarchies具有类层次结构的 Objective C Singleton
【发布时间】:2012-11-09 17:09:33
【问题描述】:

我有一个 Parent 类和一个 Child 类。 Child 派生自 Parent。我只实例化 Child 类,父级永远不会直接初始化,只有子级。 我至少需要父母成为单身人士。如果这不起作用,那么作为单身人士的孩子也可以。 我尝试了以下方法,但并没有将其更改为单例:

static MySingleton *sharedSingleton;

+ (void)initialize
{
    static BOOL initialized = NO;
    if(!initialized)
    {
        initialized = YES;
        sharedSingleton = [[MySingleton alloc] init];
    }
}

Child 类调用 [super init] 来实例化 Parent。你能帮帮我吗?

编辑:我为我的解决方案(架构)添加了一些背景信息:我有一个连接到 Web 服务的 Web 服务客户端。我有一个基类(父类),其中包含有关连接的信息(经过身份验证、如何连接等),并且我有从这个基类派生的不同子类。对不同子类的需求是一个子类负责一组 Web 服务逻辑,另一个子类负责另一组 Web 服务逻辑。问题是,我希望连接信息是单例的(因为它们都只使用一个连接,而不是很多)。

【问题讨论】:

  • 那个initialized变量是多余的,为什么不检查if (sharedSingleton == nil)呢?
  • 也许您可以简要解释一下您要实现的目标,因为让 Parent 是一个单身人士,而从中派生出一个 Child 对我来说并不显得有点混乱。或许有更好的解决方案?

标签: objective-c class inheritance singleton hierarchy


【解决方案1】:

一个更线程安全的选项是这样的:

+(MySingleton *)singleton {
    static dispatch_once_t pred;
    static MySingleton *shared = nil;

    dispatch_once(&pred, ^{
        shared = [[MySingleton alloc] init];
    });
    return shared;
}

【讨论】:

    【解决方案2】:

    如果我理解正确,您所问的内容没有意义,您似乎将 relationshipinheritance 混淆了。如果你有:

    @interface Parent : NSObject ...
    @interface Child : Parent
    

    然后每个 Child 你创建是一个 Parent 也是,不可分割的一部分,没有办法将Parent 与@ 分开987654327@ - 你只有一个对象。使用继承不会为您提供多个具有单个共享父级的子级。

    如果您希望多个孩子共享一个单亲,那么您需要您的 Child 类来拥有一个 Parent。例如:

    @interface Parent : NSObject ...
    
    @interface Child : NSObject
    
    @property (readonly) Parent *myParent;
    
    - (id) initAsChildOf:(Parent *)parent;
    
    ...
    
    @end
    

    用作:

    Parent *theParent = [Parent new];
    Child *firstChild = [[Child alloc] initAsChildOf:theParent];
    Child *secondChild = [[Child alloc] initAsChildOf:theParent];
    

    如果您愿意,可以将 Parent 设为单例类(仅可能有一个实例)或共享实例类(一个共享实例,其他可能的实例)。

    使用继承,而不是关系,很难(但并非不可能;-))从真正的单例类派生,如果这样做,派生类本身就是单例。

    您可以从共享实例类派生;并且您可以编写该类(再次困难),以便您可以拥有一个且只有一个实例,它不是派生类实例不可分割的一部分。

    注意:到目前为止,其他答案都为您提供了生成共享实例类的代码,真正的单例类涉及更多一些(您可以找到Apple 文档中的代码)并且通常一个共享实例类就足够了。

    HTH,我并没有完全误解你的问题!

    【讨论】:

    • thx,你能解释一下真正的单例和共享实例之间的区别吗?我在苹果的文档中找不到任何有用的东西(有时文档太旧了)。我在我的问题中添加了一些背景信息。你会推荐什么?
    • 一个真正的单例是一个最多可以有一个实例的类;在 Objective-C 中创建一个通常涉及覆盖 allocWithZone 和/或 init 以确保任何创建实例的尝试都返回 same 唯一实例。一个共享实例类就是一个简单的类,它有一个很容易获得的知名实例,通常使用诸如sharedInstance这样的类方法;该类的其他实例可能存在。许多 Cocoa 类遵循后来的模型,例如NSFileManager 及其 defaultManager
    • 我突然发现,如果我使用带有 dispatch_once_t 逻辑的单例代码,我就不能使用 allocWithZone。仅供参考。那么如何防止有人在我的单例上使用 alloc 呢?
    • 如果您查看基于Apple'sthis singleton 代码,您会看到它使用@synchronised 构造;如果您希望可以将该代码替换为使用 dispatch_once 的版本。
    【解决方案3】:

    把这行静态BOOL初始化=NO;在这条线下面静态 MySingleton *sharedSingleton;像这样

    static MySingleton *sharedSingleton;
    static BOOL initialized = NO;
    + (void)initialize
    {
      if(!initialized)
      {
         initialized = YES;
         sharedSingleton = [[MySingleton alloc] init];
      }
    }
    

    希望有帮助!

    【讨论】:

      【解决方案4】:

      通常的模式是:

      static MySuperclass *singleton = nil;
      + (void)initialize {
          if (self == [MySuperclass class]) {
              singleton = [[MySubclassProbabl alloc] init];
          }
      }
      

      【讨论】:

        【解决方案5】:

        与其他答案有点不同,这是创建单例的现代方式

        static MySingleton * volatile sharedInstance = nil;
        
        +(MySingleton*) sharedInstance {
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                sharedInstance = [[MySingleton alloc] init];
            });
        
            return sharedInstance;
        }
        

        此外,通过您的问题措辞和单例的预期用途(具有父/子关系),我想说您必须重新考虑您的架构。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-27
          • 1970-01-01
          • 2011-05-19
          • 1970-01-01
          • 2010-12-22
          • 1970-01-01
          相关资源
          最近更新 更多