2010-12-08 5 views
4

Есть ли способ создать шаблон Singleton с объективом-c, который позволит клиентскому коду получить общий экземпляр любого из его подклассов?Objective-c singleton baseclass

Я пробовал:

@interface Base : NSObject {} 
+(id)instance; 
@end 

@implementation Base 
static id _instance; 
+(id)instance { 
    if (!_instance) { 
     _instance = [[self alloc] init]; 
    } 
    return _instance; 
} 
@end 

Но вызов любого подкласс [AmazingThing instance] возвращает только первый экземпляр, созданный с помощью этого механизма, независимо от того, какого типа _instance есть. Любые чистые обходные пути?

Редактировать

Я понял (при ответе на удаленный ответ), что я могу делать то, что я искал, изменяя реализацию быть:

static NSMutableDictionary *_instances; 

+(id)instance { 
    if (!_instances) { 
     _instances = [[NSMutableDictionary alloc] init]; 
    } 
    id instance = [_instances objectForKey:self]; 
    if (!instance) { 
     instance = [[self alloc] init]; 
     [_instances setObject:instance forKey:self]; 
    } 
    return instance; 
} 

теперь он работает, как ожидалось. Тем не менее, мне интересно узнать, есть ли лучший способ сделать это.

+0

просто из любопытства, что такое прецедент для этого? – ennuikiller 2010-12-08 01:23:22

+0

@ennuikiller Я создаю систему сущностей/компонентов, и для целей прототипирования я хотел бы иметь синглтон из всех компонентов. – sharvey 2010-12-08 01:38:18

+0

Ваше Редактирование - довольно хорошее решение в моем случае. благодаря! – Adem 2015-11-01 21:16:36

ответ

7

Я хотел бы сделать это следующим образом:

+(id) instance 
{ 
    static id theInstance = nil; 
    if (theInstance == nil) 
    { 
     theInstance = [[self alloc] init]; 
    } 
    return theInstance; 
} 

Конечно, вы должны были бы этот метод в каждом подклассе базового класса для того, чтобы получить другую статическую переменную для каждого класса. Но вы можете создать в заголовке базового класса в #define:

#define CREATE_INSTANCE   \ 
+(id) instance     \ 
{         \ 
    static id theInstance = nil; \ 
    if (theInstance == nil)  \ 
    {        \ 
     theInstance = [[self alloc] init]; \ 
    }        \ 
    return theInstance;   \ 
} 

, а затем каждый impementation просто имеет определения в нем:

@implementation SubClass 

CREATE_INSTANCE 

// other stuff 

@end 
1

Если использовать Objective-C++ в порядке. Что вы можете сделать, это иметь метапрограммированный класс C++, который управляет временем жизни одноэлементного объекта. Таким образом, вы можете использовать шаблон Singleton и получить доступ к синглтону, используя Derived* d = Singleton<Derived>::get(). Для получения дополнительной информации вы можете посмотреть на http://src.chromium.org/viewvc/chrome/trunk/src/base/singleton_objc.h, как это делает хром.

0

Просто используйте EPPZSingleton.

Чтобы создать базовый класс, который может иметь только один подкласс, прост, но когда вы начинаете создавать все больше и больше подклассов, вы можете ожидать нежелательного поведения. EPPZSingleton решает эту проблему, поддерживая общую коллекцию синглетонов.

Смежные вопросы