这是一个创建型设计模式。
意图:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
动机:
对于一些类来说,只有一个实例是很重要的。虽然系统中可以有许多打印机,但却只能有一个打印假脱机,只应该有一个文件系统和一个窗口管理器。一个数字滤波器只能有一个A/D转换器,一个会计系统只能专用于一个公司。
我们怎么样才能保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象。
一个更好的办法是让类自己负责追踪它的唯一实例。这个类可以保证没有其他的实例可以被创建(通过截断创建新实例的请求),而且提供一种访问这个唯一实例的方法。
实现:
有一个类MazeFactory,我们要求只能有一个MazeFactory的实例。
为简单起见,我们假定不会生成MazeFactory的子类。我们通过增加静态的Instance操作和静态的用以保存唯一实例的成员_instance,从而在C++中生成一个Singleton类。我们还必须保护构造器以防止意外的实例化,因为意外的实例化可能会导致多个实例。
class MazeFactory {
public:
static MazeFactory* Instance();
protected:
MazeFactory();
private:
static MazeFactory* _instance;
};
相应的实现是:
MazeFactory* MazeFactory::_instance = 0;
MazeFactory* MazeFactory::Instance(){
if(_instance == 0){
_instance = new MazeFactory();
}
return _instance;
}
现在让我们考虑当存在MazeFactory的多个子类的时候,如何保证只有一个实例。我们将通过环境变量选择迷宫的种类并根据该环境变量的值增加代码用于实例化适当的MazeFactory子类。Instance操作是增加这些代码的好地方。
MazeFactory* MazeFactory::Instance() {
if(_instance == 0){
const char * mazeStyle = getenv("MAZESTYLE");
if(strcmp(mazeStyle,"bombed") == 0) {
_instance = new BombedMazeFactory;
}else if(strcmpp(mazeStyle,"enchanted") == 0) {
_instance = new EnchantedMazeFactory;
}
// ...other possible subclasses
}else{
_instance = new MazeFactory;
}
}
return _instance;
}
注意,针对上面的实现,任何时候当定义新的MazeFactory的子类的时候,都需要对Instance方法进行修改。在这个应用中可能没什么关系,但对于定义在一个框架中的抽象工厂来说,这可能是一个问题。一个可能的解决方法将是使用注册表的方法。