#《Head First 设计模式》例子的C++实现(4 单件模式)
单件模式使用场景比较多。基本的实现要点就是将构造函数设为私有的,这样就不能随便生成变量了。
下面是一个简单的代码示例,没有考虑多线程情况。
ChocolateBoiler 类也不希望别人拷贝,所以也把拷贝构造函数设为私有了。另外 C++与 java 最大的不同是 C++ 需要自己处理资源释放问题。所以还需要个 releaseInstance() 函数。
class ChocolateBoiler
{
public:
void boil();
bool isEmpty();
bool isBoiled();
void fill();
void drain();
static ChocolateBoiler& getInstance();
static void releaseInstance() {delete m_uniqueInstance; m_uniqueInstance = nullptr;}
private:
ChocolateBoiler();
ChocolateBoiler(ChocolateBoiler &cb){}
bool m_empty;
bool m_boiled;
static ChocolateBoiler * m_uniqueInstance;
};
ChocolateBoiler * ChocolateBoiler::m_uniqueInstance = nullptr;
ChocolateBoiler::ChocolateBoiler()
: m_empty(true), m_boiled(false)
{
}
ChocolateBoiler& ChocolateBoiler::getInstance()
{
if (m_uniqueInstance == nullptr)
{
std::cout << "Creating unique instance of Chocolate Boiler" << std::endl;
m_uniqueInstance = new ChocolateBoiler();
}
std::cout << "Returning instance of Chocolate Boiler" << std::endl;
return *m_uniqueInstance;
}
void ChocolateBoiler::boil()
{
std::cout << this << " : boil" << std::endl;
if (!isEmpty() && !isBoiled())
{
// bring the contents to a boil
m_boiled = true;
}
}
bool ChocolateBoiler::isEmpty()
{
return m_empty;
}
bool ChocolateBoiler::isBoiled()
{
return m_boiled;
}
void ChocolateBoiler::fill()
{
std::cout << this << " : fill" << std::endl;
if (isEmpty())
{
m_empty = false;
m_boiled = false;
// fill the boiler with a milk/chocolate mixture
}
}
void ChocolateBoiler::drain()
{
std::cout << this << " : drain" << std::endl;
if (!isEmpty() && isBoiled())
{
// drain the boiled milk and chocolate
m_empty = true;
}
}
测试代码如下:
ChocolateBoiler& boiler = ChocolateBoiler::getInstance();
boiler.fill();
boiler.boil();
boiler.drain();
ChocolateBoiler& boiler2 = ChocolateBoiler::getInstance();
boiler2.fill();
boiler2.boil();
boiler2.drain();
ChocolateBoiler::releaseInstance();
ChocolateBoiler& boiler3 = ChocolateBoiler::getInstance();
boiler3.fill();
boiler3.boil();
boiler3.drain();
输出结果如下:
Creating unique instance of Chocolate Boiler
Returning instance of Chocolate Boiler
0000028A02ED4F40 : fill
0000028A02ED4F40 : boil
0000028A02ED4F40 : drain
Returning instance of Chocolate Boiler
0000028A02ED4F40 : fill
0000028A02ED4F40 : boil
0000028A02ED4F40 : drain
Creating unique instance of Chocolate Boiler
Returning instance of Chocolate Boiler
0000028A02ED4F80 : fill
0000028A02ED4F80 : boil
0000028A02ED4F80 : drain
如果利用局部静态变量的特性。上面的代码还可以精简:
ChocolateBoiler& ChocolateBoiler::getInstance()
{
static ChocolateBoiler cb;
return cb;
}
这样 releaseInstance() 也不需要了。而且也不用考虑多线程加锁问题了。