好的,所以我将通过分享我自己的经验来回答这个问题。通常我希望一个类拥有它自己的所有功能,然后意识到这可能需要一个工厂方法来为其他代码提供我的对象的一个实例,该实例是单数的。实例实际上应该只定义一次以维护状态等。因此,这就是我为没有将所有初始化包装到构造中的类所做的。我不想让我现有的类因单例而混乱,所以我创建了一个工厂包装类来帮助我解决这个问题。您可以使用 Myer 的单例模式,它很优雅,并通过让静态局部变量的实现(依赖于静态局部初始化的编译器实现,这并不总是一个好主意)来处理锁定,但如果你喜欢,问题就来了我,
class X
{
public:
bool isInitialized () { return _isInitialized; } ; // or some method like
// establishCxn to have it
// bootstrapped
void initialize();
X() {} // constructor default, not initialized, light weight object
private:
bool _isInitialzied;
};
// set initialization to false
X::X(): _isInitialized(false) {}
void X::intialize()
{
if (isInitiazlied()) { return; }
.... init code ....
_isInitialized = true
}
// now we go ahead and put a factory wrapper on top of this to help manage the
// singletoness nature. This could be templatized but we don't as we want the
// flexibility to override our own getinstance to call a specific initialize for the
// object it is holding
class XFactory
{
public:
static X* getInstance();
private:
static boost::mutex _lock;
// light weight static object of yourself ( early instantiation ) to put on the stack
// to avoid thread issues, static method member thread saftey, and DCLP pattern
// threading races that can stem from compiling re-ordering of items
static XFactory _instance;
// making this pointer volatile so that the compiler knows not to reorder our
// instructions for it ( depends on compiler implementation but it is a safe guard )
X* volatile _Xitem;
X* getXitem () { return _Xitem; }
void createInstance();
void doCleanUp();
// stop instantiation or unwanted copies
XClientFactory();
~XClientFactory();
XClientFactory(XClientFactory const&);
XClientFactory& operator=(XClientFactory const&);
};
// on construction we create and set the pointer to a new light weight version of the
// object we are interested in construction
XFactory::XFactory() : _Xitem( new X; )
{
}
// note our factory method is returning a pointer to X not itself (XFactory)
X* XFactory::getInstance()
{
// DCLP pattern, first thread might have initialized X while others
// were waiting for the lock in this way your double check locking is
// on initializing the X container in the factory and not the factory object itself.
// Worst case your initialization could happen more than once but it should check the
// boolean before it starts (see initialization method above) and sets the boolean at
// the end of it. Also your init should be such that a re-initialization will not put
// the object in a bad state. The most important thing to note is that we
// moved the double check locking to the contained object's initialization method
// instead of the factory object
if (! XFactory::_instance.getXitem()->isInitialized() )
{
boost::unique_lock<boost::mutex> guard(XFactory::_lock);
if (! XFactory::_instance.getXitem()->isInitialized() )
{
XFactory::_instance.getXitem()->initialize();
}
}
return XFactory::_instance.getXitem();
}
// XFactory private static instance on the stack will get cleaned up and we need to
// call the delete on the pointer we created for the _Xitem
XFactory::~XFactory()
{
doCleanUp();
}
XFactory::doCleanUp()
{
delete _Xitem; //
}
就是这样,让我知道你的想法。我最近还与单身人士摔跤,所有的坑都掉了。此外,我们还没有使用 0x 编译器,这将确保 Myers 单例将以线程安全的方式实现,只需使用局部静态变量