带参数iOS的单例
我需要实现一个接受参数的单例类。每次都会将同一对象作为参数传递,因此生成的单例对象始终相同 我正在做下面的代码。这个看起来可以吗?有没有更好的方法来实现我想要实现的目标带参数iOS的单例,ios,objective-c,design-patterns,singleton,Ios,Objective C,Design Patterns,Singleton,我需要实现一个接受参数的单例类。每次都会将同一对象作为参数传递,因此生成的单例对象始终相同 我正在做下面的代码。这个看起来可以吗?有没有更好的方法来实现我想要实现的目标 - (id)sharedInstanceWithAccount:(UserAccount *)userAccount { if (!sharedInstance) { @synchronized(self) { sharedInstance = [[[self class] a
- (id)sharedInstanceWithAccount:(UserAccount *)userAccount {
if (!sharedInstance) {
@synchronized(self) {
sharedInstance = [[[self class] alloc] initWithAccount:userAccount];
}
}
return sharedInstance;
}
- (id)initWithAccount:(UserAccount *)userAccount {
self = [super init];
if (self) {
_userAccount = userAccount;
}
return self;
}
- (id)init {
NSAssert(false,
@"You cannot init this class directly. It needs UserAccountDataSource as a paramter");
return nil;
}
+ (id)alloc {
@synchronized(self) {
NSAssert(sharedInstance == nil, @"Attempted to allocated a second instance of the singleton");
sharedInstance = [super alloc];
return sharedInstance;
}
return nil;
}
B被忽略。
objB中的userAccount是一个
如果用户帐户B在objB中,您将更改sharedInstanceWithAccount
- (id)sharedInstanceWithAccount:(UserAccount *)userAccount {
static NSMutableDictionary *instanceByAccount = [[NSMutableDictionary alloc] init];
id instance = instanceByAccount[userAccount];
if (!instance) {
@synchronized(self) {
instance = [[[self class] alloc] initWithAccount:userAccount];
instanceByAccount[userAccount] = instance;
}
}
return instance;
}
此设计中存在许多问题:
一次分派\u
,而不是@synchronized(self)
:
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
有关更多详细信息,请参阅此问题:API
设计将singleton放入alloc
正如alloc方法的名称所示,这意味着将分配一些内存。然而,在你的情况下,情况并非如此。这种覆盖alloc
的尝试会使团队中的其他程序员感到困惑-init
中使用NSAssert
是个坏主意
如果要禁用某个方法,请将其放入头文件中禁用:
- (id)init __attribute__((unavailable));
在这种情况下,您将得到一个编译错误,而不是在运行时使应用程序崩溃。
有关更多详细信息,请参阅本文:
此外,您甚至可以添加不可用的消息:
- (id)init __attribute__((unavailable("You cannot init this class directly. It needs UserAccountDataSource as a parameter")));
userAccount
有时会被忽略
- (id)sharedInstanceWithAccount:(UserAccount *)userAccount {
if (!sharedInstance) {
@synchronized(self) {
sharedInstance = [[[self class] alloc] initWithAccount:userAccount];
}
}
return sharedInstance;
}
简言之,不要认为使用参数创建singleton是个好主意。使用传统的单例设计要干净得多 这可能是为什么单身是个坏主意的另一个迹象。在这种情况下,您可能会更好地使用依赖项注入,但即使我使用依赖项注入,我如何传入userAccount对象?当您实例化
MyClass
时,您将调用initWithAccount
,然后将此对象传递给需要您的MyClass
实例的所有其他类,我很抱歉也许我不明白这是对的。下面的函数-(id)sharedInstanceWithAccount:(UserAccount*)UserAccount{if(!sharedInstance){@synchronized(self){sharedInstance=[[self class]alloc]initWithAccount:UserAccount];}}}返回sharedInstance;}带参数的单例的问题是,可能会有两个不同的调用sharedInstanceWithAccount
来传递不同的帐户(我知道你说不会,但这仍然是可能的)。您可以根据答案使用一个工厂模式,并使用字典,或者忘记单例,实例化单类实例并使用依赖项注入将其传递给每个需要它的类。那么,我如何实现我正在尝试的呢?我只想在应用程序中存在该类的一个副本,这取决于UserAccount。是的,如果使用singleton,您将只有该类的一个副本。如果你想让它依赖于UserAccount,只需在获得singleton后修改该值即可。我的意思是,在构造类时,如何将UserAccount对象传递给类而不引入参数?我可以将其设置为属性,稍后再进行设置,但如果有人忘记设置属性,则会再次出现问题。好的,您可以看看我对该问题的编辑吗?也许这就是你要找的。
- (id)sharedInstanceWithAccount:(UserAccount *)userAccount {
if (!sharedInstance) {
@synchronized(self) {
sharedInstance = [[[self class] alloc] initWithAccount:userAccount];
}
}
return sharedInstance;
}