Singleton模式

来源:互联网 发布:北大光华mba 知乎 编辑:程序博客网 时间:2024/04/29 20:47

Singleton

中文名称

    单件。

意图

    保证一个类只有一个实例,并且提供一个全局存取点。

问题

    应用需要且只需要一个对象的一个实例。此外,延迟初始化和全局存取是必需的。

讨论

    对于某个类,无论是创建,初始化,存取还是执行,确保只有一个实例。把实例作为一私有静态数据成员声明,提供一个公有静态成员函数封装所有初始化代码,提供对实例的存取。

    当需要单独实例的引用时,客户调用存取函数(使用类名::操作)。

    Singleton仅在以下三个标准都满足时被考虑:

  • 单独实例的拥有者难以合理分配。
  • 期望延迟初始化。
  • 没有提供全局存取。

    Singleton模式可以扩展以支持特定数目的实例。

    “静态成员函数存取”方法不支持Singleton类的子类化。

    删除一个Singleton类/对象不是一个可有可无的问题。

 

示例

    美国总统是一个Singleton。美国宪法指定了怎样选举总统,限制了此职位的期限,定义了连任顺序。因此,任何时间最多只有一个现任总统。不管现任总统的个人特性如何,“美国总统”的称号是在职者的全局存取点。

 

其他看法

    Singleton不能解决全局变量问题,它只是保证一个类仅有一个实例的模式。至于全局变量,唯一的好处就是减少名字空间。

    Singleton比全局变量好的地方是能确认有几个实例在被使用。

    解决全局变量的答案不是Singleton模式,而是不要使用。

经验规则

    Abstract Factory,Builder和 Prototype在实现中能使用Singleton。

    Facade通常是Singletons,因为只需要一个Facade对象。

    State对象通常是Singleton。

// 讨论:Singleton 
// 
//
讨论:第一个例子中,一个全局对象需要延迟初始化(需要时再初始化)。
// 这需要所有用户检测,并可能分配指针。
// Singleton提倡让对象自身有职责创建,维护,自身的唯一实例,
// 并提供全局访问点。


#include <iostream.h> 

class GlobalClass { 
    public
    GlobalClass( int v=0 ) { 
        value_ = v; } 
    int getValue() { 
        return value_; } 
    void setValue( int v ) { 
    value_ = v; } 
private
    int value_; 
}; 

//
初始化GlobalClass类的全局指针 
GlobalClass* globalObj = 0; 

void foo( void

    if ( ! globalObj ) 
        globalObj = new GlobalClass; 
    globalObj->setValue( 1 ); 
    cout << "foo: globalObj is " <<
    globalObj->getValue() << endl; 


void bar( void

    if ( ! globalObj ) 
        globalObj = new GlobalClass; 
    globalObj->setValue( 2 );
    cout << "bar: globalObj is " << 
    globalObj->getValue() << endl; 


void main( void

    if ( ! globalObj ) 
        globalObj = new GlobalClass;
    cout << "main: globalObj is " <<  globalObj->getValue() << endl; 
    foo(); 
    bar(); 


// main: globalObj is 0 
// foo: globalObj is 1 
// bar: globalObj is 2

// 新的设计:“globalObj”现在是自身类的一个私有静态成员函数。
// 通过公有静态成员函数inst()提供了全局访问点。
// 延缓初始化代码在inst()函数中被封装。
// GlobalClass的构造和析构函数是受保护的,
// 用户不能创建更多的实例,也不能销毁Singleton实例。


class GlobalClass {
public:
    int getValue() {
        return value_; }
    void setValue( int v ) {
        value_ = v; }
    static GlobalClass* inst() {
        if ( ! globalObj_ )
            globalObj_ = new GlobalClass;
    return globalObj_; }
protected:
    GlobalClass( int v=0 ) {
        value_ = v; }
    ~GlobalClass() { }
private:
    int value_;
    static GlobalClass* globalObj_;
};

GlobalClass* GlobalClass::globalObj_ = 0;

void foo( void )
{
    GlobalClass::inst()->setValue( 1 );
    cout << "foo: globalObj is " << GlobalClass::inst()->getValue() << endl;
}

void bar( void )
{
    GlobalClass::inst()->setValue( 2 );
    cout << "bar: globalObj is " << GlobalClass::inst()->getValue() << endl;
}

void main( void )
{
    cout << "main: globalObj is " << GlobalClass::inst()->getValue() << endl;
    foo();
    bar();
}

// main: globalObj is 0
// foo: globalObj is 1
// bar: globalObj is 2

// 讨论:Singleton析构

class GlobalClass;

class SingDest {
public:
    SingDest( GlobalClass* s=0 ) {
    sing_ = s; }
    ~SingDest();
void setSing( GlobalClass* s ) {
    sing_ = s; }
private:
    GlobalClass* sing_;
};

class GlobalClass {
public:
    friend class SingDest;
    int getValue() { return value_; }
    void setValue( int v ) {
        value_ = v; }
    static GlobalClass* inst() {
        if ( ! globalObj_ ) {
            globalObj_ = new GlobalClass;
            dest_.setSing( globalObj_ ); }
        return globalObj_; }
private:
    GlobalClass( int v=0 ) {
        cout << ":ctor: ";
        value_ = v; }
    ~GlobalClass() {
        cout << ":dtor:" << endl; }
int value_;
    static GlobalClass* globalObj_;
    static SingDest dest_;
};

GlobalClass* GlobalClass::globalObj_ = 0;
SingDest GlobalClass::dest_;
SingDest::~SingDest() { delete sing_; }

void foo( void )
{
    GlobalClass::inst()->setValue( 1 );
    cout << "foo: globalObj is " << GlobalClass::inst()->getValue() << endl;
}

void bar( void )
{
    GlobalClass::inst()->setValue( 2 );
    cout << "bar: globalObj is " << GlobalClass::inst()->getValue() << endl;
}


void
main( void )
{
    cout << "main: globalObj is " << GlobalClass::inst()->getValue() << endl;
    foo();
    bar();
}


// main: globalObj is :ctor: 0
// foo: globalObj is 1
// bar: globalObj is 2
// main: end
// :dtor:

// 目的:Scott Meyers方法。
// globalObj”现在是访问方inst()的静态成员。
// 通过声明构造函数非公有强制单实例。
// 因为静态变量实例,析构函数必须是公有的。
// inst()静态方法提供访问。
// C++第一次要求时,对象被分配;然后C++能自动销毁它。


#include <iostream.h>

class GlobalClass {
    public:
    int getValue() {
        return value_; }
    void setValue( int v ) {
        value_ = v; }
    static GlobalClass& inst() {
        static GlobalClass globalObj;
        return globalObj; }
    ~GlobalClass() {
        cout << ":dtor:" << endl; }
protected:
    GlobalClass( int v=0 ) {
        cout << ":ctor: ";
        value_ = v; }
private:
    int value_;
};

void foo( void )
{
    GlobalClass::inst().setValue( 1 );
    cout << "foo: globalObj is " <<
    GlobalClass::inst().getValue() << endl;
}

void bar( void )
{
    GlobalClass::inst().setValue( 2 );
    cout << "bar: globalObj is " <<
    GlobalClass::inst().getValue()<< endl;
}

void main( void )
{
    cout << "main: globalObj is " << GlobalClass::inst().getValue() << endl;
    foo();
    bar();
    cout << "main: end" << endl;
}

// main: globalObj is :ctor: 0
// foo: globalObj is 1
// bar: globalObj is 2
// main: end
// :dtor:

// 讨论:Singleton设计模式,支持继承

// 1. 在类中定义一个私有静态属性。
// 2. 在类中定义一个公有静态访问函数。
// 3. 在访问函数中作“延缓初始化”(根据命令创建)。
// 4. 定义所有构造函数受保护或者私有。
// 5. 用户只能使用访问函数来操纵 Singleton
// 6. 能支持继承,但是不能覆盖静态函数。
// 基类必须被声明为派生类的友元,以访问受保护的构造函数。


#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;

class Number {
public:
    static Number* instance(); // 2.
在类中定义一个公有静态访问函数。
    static void setType( string t ) { type = t; delete inst; inst = 0;}
    virtual void setValue( int in ) { value = in; }
    virtual int getValue() { return value; }
protected:
    int value;
    Number() { cout << ":ctor: "; }
// 4. 定义所有构造函数受保护或者私有
private:
    static string type;
    static Number* inst;
// 1. 在类中定义一个私有静态属性。
};

string Number::type = "decimal";
Number* Number::inst = 0;

class Octal : public Number { // 6.
能支持继承,但是不能覆盖静态函数。
public:
    friend class Number;
    void setValue( int in ) {
        char buf[10];
        sprintf( buf, "%o", in );
        sscanf( buf, "%d", &value );
    }
protected:
    Octal() { }
};

Number* Number::instance() {
    if ( ! inst)
   
// 3. 在访问函数中作“延缓初始化”。
    if (type == "octal") inst = new Octal();
    else inst = new Number();
    return inst;
}

void main( void ) {
    // Number myInstance; ---
错误: 不能访问受保护构造函数
    // 5. 用户只能使用访问函数来操纵 Singleton
    Number::instance()->setValue( 42 );
    cout << "value is " << Number::instance()->getValue() << endl;
    Number::setType( "octal" );
    Number::instance()->setValue( 64 );
    cout << "value is " << Number::instance()->getValue() << endl;
}

// :ctor: value is 42
// :ctor: value is 100

原创粉丝点击