I've been reading a lot of debates about whether the Singleton pattern is good/bad/ugly, and what should be used instead of it.
The common implementation requires an Instance()
method that invokes a private constructor if the object has not yet been created.
My question doesn't really fit the Singleton pattern, but would it be possible to limit the number of instances of a class by overriding new
? And if say we only want one instance, return the already created instance?
If this is pos开发者_开发知识库sible is it even a good idea?
The aim would be that in any class needing access to a class, one would simply declare a private member, which would be initialized the first time, and then referenced for the rest.
ClassA {
MyClass classRef;
}
ClassB {
MyClass classRef;
}
So if MyClass
is limited to one instance, depending on the order of instancing, one of these objects will actually create a new MyClass, and the other will just obtain it's reference.
Objects can be allocated statically, on the stack, and within other objects. If you want just one instance, you need to disallow all of these somehow. Overloading operator new
won't help you with this. Making the constructors private
or protected
will, but this will disable operator new
for the users of the class as well.
Moreover, what operator new
returns is not an object, but a block memory in which the object will be created. If you return an already allocated block, a constructor will be run over it each time operator new
is called.
This sounds like a non-concurrent worker pool of some sort.
This can be a good idea when a large number of jobs are going to be executed by more than one service/driver and you want to implement throttling, or perhaps queue jobs to prevent swap file thrashing, or some other resource constraint.
Overriding new
is probably not the right way to do it. Have the task farm be an object itself, and "allocate" tasks from there. The raw allocation of the task handle wrapper object should be free from such considerations.
And yes, singletons are ugly (or at least an ugly implementation of a good idea).
Overriding new
won't work. First, it won't prevent additional
instances on the stack or as static variables. Second, the operator
new
that you define only allocates memory; the constructor will still
be called (with possibly disasterous effects if the singleton has
mutable state).
You can limit the number of instantiations much more straightforwardly by keeping a counter as a static member variable:
template<unsigned int N>
class N_gleton {
private:
static int number_of_instances_;
public:
enum { MAX_NUMBER_OF_INSTANCES = N };
N_gleton() {
assert(number_of_instances_ < MAX_NUMBER_OF_INSTANCES);
++number_of_instances_;
}
};
template<unsigned int N>
int N_gleton<N>::number_of_instances_ = 0; // initial value
精彩评论