创建具有类层次结构dispatch_once的单一实例类



我有一个继承自"MyClass"的 2 个子类,每个子类都应该是一个单例。

当我没有任何其他类继承时,我使用此模式来获取静态实例:

+ (MyClass *)getInstance
{
static dispatch_once_t once;
static MyClass *instance;
dispatch_once(&once, ^{
instance = [[MyClass alloc] init];
});
return instance;
}

这很好用。现在,如果我添加两个新的子类,FirstClass 和 SecondClass,这两个子类都继承自 MyClass,如何确保我能取回各自的 ChildClass?

dispatch_once(&once, ^{
// No longer referencing 'MyClass' and instead the correct instance type
instance = [[[self class] alloc] init];
});
FirstClass *firstClass = [FirstClass getInstance]; // should be of FirstClass type
SecondClass *secondClass = [SecondClass getInstance]; // should be of SecondClass type

执行上述操作意味着我总是将我实例化为 1st 的任何类作为我的第二个类类型:

first: <FirstClass: 0x884b720>
second: <FirstClass: 0x884b720>
// Note that the address and type as identical for both.

在不向每个子类添加getInstance方法的情况下创建相应的子类单例的最佳方法是什么?

除非你有充分的理由,否则通常应该避免对单例进行子类化。它造成了一个非常混乱的情况。如果创建一个单例MyClass,那么可以创建一个单例FirstClass吗?由于FirstClass必须始终可在任何可用MyClass(由 Liskov)使用,因此现在有三个"单例"MyClass对象。现在 ObjC 对单例非常松散,这是一件好事,但这仍然很奇怪。

好吧,也就是说,你的问题呢?首先是解决方案,然后是答案。解决方案是MyClass可能不应该是单例,如上所述。摆脱超类中的getInstance,只需在子类中定义它。

正在发生的事情的答案就在你dispatch_once.在所有情况下,您都会传递相同的静态once令牌。 对于给定令牌,dispatch_once运行次数不会超过一次。解决此问题的唯一方法是为每个类传递不同的令牌,我不知道在不复制每个文件中的dispatch_once代码的情况下,有什么方便的方法可以做到这一点。您可以尝试为每个子类创建不同的once标记,但这可能比仅仅复制sharedInstance方法更麻烦和代码。

顺便说一句,不要称它为getInstance."get"在 ObjC 中具有特殊含义,而您在这里不是这个意思,所以它令人困惑。这通常被称为sharedInstance,或者更好的sharedSomething"某物"是你的类。如果你真的的意思是应该有一个MyClass,应该有一个FirstClass,应该有一个SecondClass,你可以在这三个中实现sharedInstance

你知道单身人士很粗糙,对吧? 许多单身人士是一个更大的问题。 谨慎结束。


你可以只使用dispatch_once来创建基本单例。 然后你的基可以保存其派生类型的映射(例如字典{key:ClassName|value:Instance})。

您正在使用dispatch_once表明这将在多线程上下文中使用。 在这种情况下,您需要使用互斥锁保护与字典的交互。

然后,来自子类的消息将根据消息传递类(self)确定要查找的类(如有必要,创建该实例)。

在头等舱的myClass中使用id喜欢这个

+(instancetype)sharedInstance 
{
static id sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[[self class] alloc] init];
});
return sharedInstance;
}

我认为这应该有效

最新更新