C ++:Singleton的替换

时间:2011-07-14 04:14:08

标签: c++ class singleton

我经常使用单例,因为我讨厌将主类的对象传递给成员类,以便允许它们访问主类。

Class Foo
{
    A* a;
    B* b;
    C* c;
};

例如在上面的例子中,如果A,B和C想要访问Foo-我将不得不传递Foo的每一个对象,并将其存储为其成员变量(或者在每个函数中给出对象)呼叫)。这有效,但感觉不对,需要更多的代码编写。

相反,我可以让Foo成为单身人士(当然只有在只有1个实例的情况下)然后从A,B和C调用Foo :: getInstance() - > ...我不会必须传递任何对象。我觉得这很方便。

现在,问题是我的情况可能有多个Foo实例。显然我不能使用单身模式。但我不想传递变量,也不想将它们存储在成员类中。代码太多了! :)

举个例子, 我讨厌这个:

A::A(Foo* foo) : m_foo(foo)
{

}

和此:

void A::someFunc(Foo* foo, int someParam)
{

}

但是,我喜欢这个:

A::A()
{

}

void A::someFunc(int someParam)
{
    Foo* foo = Foo::getInstance();
}

还有其他办法吗?什么东西类似于单身人士模式?

4 个答案:

答案 0 :(得分:7)

这种模式正在创建一堆循环引用,通常是代码气味。您可能希望深入了解您的设计,因为解决这些关系问题的常用方法是创建一个与现有类交互的第三个类。或者,如果你真的需要这种行为,那么传递对包含类的引用有什么问题呢?

答案 1 :(得分:1)

让您的单身class成为template

template<unsigned int NUMBER>
class Foo
{
  A* a;
  B* b;
  C* c;
};

并使用您想要的任何实例。它仍将保持单身,但您可以拥有多个对象:

Foo<1>;
Foo<2>;
Foo<3>;

答案 2 :(得分:0)

我在一些项目中完成了这项工作。这里有一些伪代码可以让您了解我是如何完成它的:

static map<string, Foo*> instances;

static Foo* Foo::getInstance(string name)
{
    Foo* inst = NULL;

    lock(instances);
    if(instances.count(name) > 0)
    {
        inst = instances[name];
    }
    else
    {
        inst = new Foo();
        instances[name] = inst;
    }

    unlock(instances);
    return inst;
}

然后你只需要调用Foo :: getInstance(“instance1”)或Foo :: getInstance(“instance2”)等等。所有你需要做的就是记住一个字符串,有点好(我想)。我不知道这个设计模式是否有正式的名称,如果有人请告诉我,所以在将来描述这个时我听起来并不那么无知。

答案 3 :(得分:0)

单身人士是邪恶的,我们都同意。但之所以经常被遗忘。这不是因为它们本质上是一个全球性的。当他们解决问题时,Globals非常棒。单身人士的问题在于他们结合了生命周期,初始化顺序和全局访问。

听起来你需要一个全局的,所以使用全局。

A* g_a;
B* g_b;
C* g_c;

在其他任何需要访问它们之前初始化main中的所有全局变量。

或者做得更聪明。

template< typename T >
T& instance( void );

template< typename T >
void set_instance( T& t );

void needs_an_A( void )
{
   instance<A>().a_stuff();
}

或者最重要的是将其与RAII联系起来:

void needs_a_b( void )
{
   B& b = instance<B>();
   b.stuff();
   b.more_stuff();
}

int main()
{
   Initializer<A> init_a;
   Initializer<B> init_b;  // B needs an A during construction
   Initializer<C> init_c( "C constructor param" );

   needs_a_b();
}