我有一个继承自"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;
}
我认为这应该有效