单例模式是另一种流行的设计模式。它保证在程序执行期间只有一个实例在运行。也就是我们只使用同一个实例。
我们将使用上一节的ColorDetectController类。稍微修改一下获得一个Singleton类。首先我们要添加一个私有静态成员变量。另外为了防止创建类,初始化器是私有的。
class ColorDetectController {
private:
// pointer to the singleton
static ColorDetectController *singleton;
ColorDetector *cdetect;
// private constructor
ColorDetectController() {
//setting up the application
cdetect= new ColorDetector();
}
除此之外,你也可以使复制构造器和操作符“=”变为私有,使任何人都不可以创建类的副本。单例对象按需创建。我们使用一个静态方法创建一个实例,然后返回指向实例的指针。
// Gets access to Singleton instance
static ColorDetectController *getInstance() {
// Creates the instance at first call
if (singleton == 0)
singleton= new ColorDetectController;
return singleton;
}
注意到这个单例是线程不安全的,因此,并行线程不能方位这个单例实例。最后一,由于单例实例是动态创建,所以在不使用时必须手动删除。删除的方法也是一个静态方法。
// Releases the singleton instance of this controller.
static void destroy() {
if (singleton != 0) {
delete singleton;
singleton= 0;
}
}
因为singleton是一个静态成员变量,所以必须定义.cpp文件,所以:
#include "colorDetectController.h"
ColorDetectController *ColorDetectController::singleton=0;
因为单例可以通过公共的静态方法获得,所以多有含有单例类的类都会访问同一个类。这对于有许多交互按钮的复杂界面非常有利。由于是静态类,所以不需要声明创建一个实例了:
// Callback method of "Open" button.
void OnOpen()
{
...
// if a filename has beed selected
if (dlg.DoModal() == IDOK) {
// get the path of the selected filename
std::string filename= dlg.GetPathName();
// set and display the input image
ColorDetectController::
getInstance()->setInputImage(filename);
cv::imshow("Input Image",
ColorDetectController::
getInstance()->getInputImage());
}
}
// Callback method of "Process" button.
OnProcess()
{
// target color is hard-coded here
ColorDetectController::
getInstance()->setTargetColor(130,190,230);
// process the input image and display result
ColorDetectController::getInstance()->process();
cv::imshow("Output Result",
ColorDetectController::getInstance()->getLastResult());
}
当应用关闭时,释放这个单例实例
// Callback method of "Close" button.
void OnClose()
{
// Releases the Singleton.
ColorDetectController::getInstance()->destroy();
OnOK();
}
从上面我们可以看出,当一个Controller类封装在一个单例中时,可以从任何类中访问这个类。