Using [self class] is really a waste in this case - M1 and M3 aren't really that different unless you have subclasses involved, and the reality is that the rest of the implementation isn't up to it.
Consider what happens if you create a subclass of ReactorClass like this:
@interface MyReactorClass : ReactorClass {}
@end
@implementation MyReactorClass
@end
If you call [MyReactorClass sharedInstance] you can see that its reading from a single static variable sharedReactor. Thats ok if you only create one subclass but you need to be very conscious of that, and the fact that any 3rd party libraries you call don't also use the same base class for the singletons they create but you don't know about. If, as Mark suggested, you copy the M3 code into your subclass, it will work better but you need to ask yourself "why did I subclass this?" - you got little benefit and would have been better off coding it completely, instead of relying on the implementation details of the superclass.
To do it properly, you'd keep a static dictionary (create during the +initialise of the base class), and insert entries into it keyed by the actual class of the singleton you were creating.
Worrying about whether to override alloc or allocWithZone: is again a subclassing thing but really, anyone who inherits from a singleton superclass and then screws around with its allocation methods deserves the bad behaviour they get. If you want to code the perfect singleton base class, you should create and DOCUMENT additional methods that get called so that subclassers can solve any problem they might think of without messing with your infrastructure.
Personally, my singletons throw exceptions out of all methods starting with init and do their real initialisation in an unknown method (ok, its called _init) - that GUARANTEES that people misusing the singleton class don't get unexpected behaviour.
It really boils down to "how much do you trust your subclasser". If you assume he's an idiot, you need to override things like release, retain, etc. If you assume he follows the memory management rules, you can leave those things alone because they'll just work. Apple are really a bit stupid in this regard in their sample code; they are somewhat paranoid but nowhere near idiot-proof.