最佳的单例模式与虚拟方法组织方式

3
我将翻译如下:

我正在开发一个用C++编写的简单框架。现在我有如下文件:

app.cpp

#include "app.h"

namespace App
{

}

void App::init()
{

}

void App::timerEvent(int time)
{

}

如果有时我不想监听 timerEvent 会怎么样?我仍然必须编写空方法实现。

我的想法是从命名空间移到 class App : public BaseApp,并在 BaseApp 中使用 virtual void BaseApp::init() = 0virtual void BaseApp::timerEvent(int time) {}(类似于 Qt 的 QApplication)。但是,App 必须是单例模式的,但我没有看到任何一种方式可以从 BaseApp 指定它,因此我必须在 App 中编写单例模式代码,而所有虚拟概念都没有意义。

我应该如何设计它?

P.S. 我不想在这里使用监听器。对我来说,这似乎过度了。

P.P.S. 我需要单例模式,因为我从 main 初始化 app 实例,但仍然希望从另一个类访问其方法。


3
我并不完全理解所有的内容,但无论如何,请不要使用单例模式,并基于该原则设计您的架构。 - Christian Hackl
你可以选择只创建一个 App 对象。你不需要使用单例模式来做出这个选择。 - Galik
@Galik 但我没有看到其他的可能性。我想从另一个代码部分调用我的应用程序实例方法。 - Ximik
1
@Ximik 依赖注入是一种可能性。只需将对您的 App 的引用传递给需要调用其成员函数的任何函数或对象即可。 - Joseph Thomson
@JosephThomson 是的,好主意,谢谢。 - Ximik
你可以在单例的 instance() 方法中添加一个模板参数,并将你特定的应用类型作为模板参数传递。可以使用 static_assert() 来确保模板参数是派生类型。 - Galik
1个回答

2

您可以使用函数指针或std::function在命名空间内模拟虚函数。只需像这样创建:

#include "app.h"

namespace App
{
    std::function<void(int)> vtTimerEvent;
}

void App::timerEventImpl(int time)
{
    // default timerEvent implementation
}

void App::init(std::function<void(int)> timerEvent = &App::timerEventImpl)
{
    vtTimerEvent = timerEvent;
}

void App::timerEvent(int time)
{
   vtTimerEvent(time);
}

这并不是非常出色的设计,但它可以实现你想要的功能。

更新

另一个近似解:

#include <memory>
#include <stdexcept>

// virtual base interface
class IInterface
{
public:
    virtual ~IInterface() = 0;
};

IInterface::~IInterface(){} // must have

// virtual App interface
class IApp :
    virtual public IInterface
{
public:
    virtual void init() = 0;
    virtual void timerEvent(int time) = 0;
};


// static App interface
class App
{
private:
    ~App(); // nobody can create an instance
public:
    static void init(const std::shared_ptr<IApp> &impl_p)
    {
        if (!impl)
        {
            impl = impl_p;
            impl->init();
        }
        else
        {
            throw std::runtime_error("Already initialized");
        }
    }

    static void timerEvent(int time)
    {
        impl->timerEvent(time);
    }
private:
    static std::shared_ptr<IApp> impl;
};

std::shared_ptr<IApp> App::impl;

// specific App implementation
class AppImplementation1 :
    public IApp
{
    //...
};


int main(int, char**)
{
    auto myImpl = std::make_shared<AppImplementation1>();
    App::init(myImpl);
    //...
    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接