Использование [self class] в этом случае - пустая трата времени - M1 и M3 не сильно отличаются друг от друга, если не задействованы подклассы, а реальность такова, что остальная часть реализации не до этого.
Рассмотрим, что произойдет, если вы создадите подкласс ReactorClass следующим образом:
@interface MyReactorClass : ReactorClass {}
@end
@implementation MyReactorClass
@end
Если вы вызываете [MyReactorClass sharedInstance], вы можете видеть, что он читает из одной статической переменной sharedReactor. Ничего страшного, если вы создаете только один подкласс, но вам нужно это осознавать, и тот факт, что любые сторонние библиотеки, которые вы вызываете, также не используют тот же базовый класс для создаваемых ими синглетонов, о которых вы не знаете. Если, как предложил Марк, вы скопируете код M3 в свой подкласс, он будет работать лучше, но вам нужно спросить себя: «Почему я это сделал подклассом?» - вы получили небольшую выгоду и вам лучше было бы полностью ее кодировать, а не полагаться на детали реализации суперкласса.
Чтобы сделать это правильно, вы должны сохранить статический словарь (создать во время инициализации + базового класса) и вставить в него записи, основанные на фактическом классе создаваемого вами синглтона.
Беспокойство о том, стоит ли переопределять alloc или allocWithZone: опять же вещь подкласса, но на самом деле, любой, кто наследует от одноэлементного суперкласса, а затем разбирается с его методами выделения, заслуживает плохого поведения, которое они получают. Если вы хотите закодировать идеальный одноэлементный базовый класс, вы должны создать и DOCUMENT дополнительные вызываемые методы, чтобы субклассеры могли решить любую проблему, о которой они могли подумать, не вмешиваясь в вашу инфраструктуру.
Лично мои синглеты выбрасывают исключения из всех методов, начинающихся с init, и выполняют их настоящую инициализацию в неизвестном методе (хорошо, это называется _init) - что ГАРАНТИРУЕТ, что люди, неправильно использующие одноэлементный класс, не делают получить неожиданное поведение.
Это действительно сводится к тому, "насколько вы доверяете своему субклассеру". Если вы предполагаете, что он идиот, вам нужно переопределить такие вещи, как освобождение, сохранение и т. Д. Если вы предполагаете, что он следует правилам управления памятью, вы можете оставить эти вещи в покое, потому что они просто будут работать. Apple действительно немного глупа в этом отношении в своем примере кода; они несколько параноидальны, но отнюдь не дураки.